Selaa lähdekoodia

Merge topic 'refactor-cmListFileBacktrace'

d2475bb5 cmListFileBacktrace: Implement in terms of cmState::Snapshot.
238aac23 cmListFile: Remove FilePath member from cmListFileContext.
329098a9 cmMakefile: Set the FilePath on the frame from the cmState.
91158a33 cmMakefile: Create intermediate variables for snapshot frames.
821f91d6 cmMakefile: Create a scoped context for parsing listfiles.
30d44efa cmMakefile: Access the execution list file from the cmState.
6361f680 cmState: Store execution context.
94704d75 cmState: Add GetCallStackParent method.
a8e54460 cmState: Store snapshots for more different types.
dbafb015 cmMakefile: Split CallStack into two pieces.
27ff19a9 cmLinkedTree: Add operator* to the iterator.
Brad King 10 vuotta sitten
vanhempi
sitoutus
b33b5cd317

+ 1 - 0
Source/cmFunctionCommand.cxx

@@ -95,6 +95,7 @@ bool cmFunctionHelperCommand::InvokeInitialPass
     }
 
   cmMakefile::FunctionPushPop functionScope(this->Makefile,
+                                            this->FilePath,
                                             this->Policies);
 
   // set the value of argc

+ 18 - 0
Source/cmLinkedTree.h

@@ -87,6 +87,24 @@ public:
       return this->Tree->GetPointer(this->Position - 1);
     }
 
+    ReferenceType operator*() const
+    {
+      assert(this->Tree);
+      assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
+      assert(this->Position <= this->Tree->Data.size());
+      assert(this->Position > 0);
+      return this->Tree->GetReference(this->Position - 1);
+    }
+
+    ReferenceType operator*()
+    {
+      assert(this->Tree);
+      assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
+      assert(this->Position <= this->Tree->Data.size());
+      assert(this->Position > 0);
+      return this->Tree->GetReference(this->Position - 1);
+    }
+
     bool operator==(iterator other) const
     {
       assert(this->Tree);

+ 24 - 15
Source/cmListFileCache.cxx

@@ -251,7 +251,6 @@ bool cmListFileParser::ParseFunction(const char* name, long line)
 {
   // Inintialize a new function call.
   this->Function = cmListFileFunction();
-  this->Function.FilePath = this->FileName;
   this->Function.Name = name;
   this->Function.Line = line;
 
@@ -399,40 +398,50 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token,
     }
 }
 
-void cmListFileBacktrace::Append(cmListFileContext const& context)
-{
-  this->push_back(context);
-}
-
 void cmListFileBacktrace::PrintTitle(std::ostream& out)
 {
-  if (this->empty())
+  if (!this->Snapshot.IsValid())
     {
     return;
     }
-
   cmOutputConverter converter(this->Snapshot);
-  cmListFileContext lfc = this->front();
+  cmListFileContext lfc =
+      cmListFileContext::FromCommandContext(
+        this->Context, this->Snapshot.GetExecutionListFile());
   lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME);
   out << (lfc.Line ? " at " : " in ") << lfc;
 }
 
 void cmListFileBacktrace::PrintCallStack(std::ostream& out)
 {
-  if (size() <= 1)
+  if (!this->Snapshot.IsValid())
+    {
+    return;
+    }
+  cmState::Snapshot parent = this->Snapshot.GetCallStackParent();
+  if (!parent.IsValid() || parent.GetExecutionListFile().empty())
     {
     return;
     }
 
   cmOutputConverter converter(this->Snapshot);
-  const_iterator i = this->begin() + 1;
+  std::string commandName = this->Snapshot.GetEntryPointCommand();
+  long commandLine = this->Snapshot.GetEntryPointLine();
+
   out << "Call Stack (most recent call first):\n";
-  while(i != this->end())
+  while(parent.IsValid())
     {
-    cmListFileContext lfc = *i;
-    lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME);
+    cmListFileContext lfc;
+    lfc.Name = commandName;
+    lfc.Line = commandLine;
+
+    lfc.FilePath = converter.Convert(parent.GetExecutionListFile(),
+                                     cmOutputConverter::HOME);
     out << "  " << lfc << "\n";
-    ++i;
+
+    commandName = parent.GetEntryPointCommand();
+    commandLine = parent.GetEntryPointLine();
+    parent = parent.GetCallStackParent();
     }
 }
 

+ 23 - 6
Source/cmListFileCache.h

@@ -25,6 +25,13 @@
 
 class cmMakefile;
 
+struct cmCommandContext
+{
+  std::string Name;
+  long Line;
+  cmCommandContext(): Name(), Line(0) {}
+};
+
 struct cmListFileArgument
 {
   enum Delimiter
@@ -57,6 +64,16 @@ struct cmListFileContext
   std::string FilePath;
   long Line;
   cmListFileContext(): Name(), FilePath(), Line(0) {}
+
+  static cmListFileContext FromCommandContext(cmCommandContext const& lfcc,
+                                              std::string const& fileName)
+  {
+    cmListFileContext lfc;
+    lfc.FilePath = fileName;
+    lfc.Line = lfcc.Line;
+    lfc.Name = lfcc.Name;
+    return lfc;
+  }
 };
 
 std::ostream& operator<<(std::ostream&, cmListFileContext const&);
@@ -64,24 +81,24 @@ bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs);
 bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs);
 bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs);
 
-struct cmListFileFunction: public cmListFileContext
+struct cmListFileFunction: public cmCommandContext
 {
   std::vector<cmListFileArgument> Arguments;
 };
 
-class cmListFileBacktrace: private std::vector<cmListFileContext>
+class cmListFileBacktrace
 {
   public:
-    cmListFileBacktrace(cmState::Snapshot snapshot = cmState::Snapshot())
-      : Snapshot(snapshot)
+    cmListFileBacktrace(cmState::Snapshot snapshot = cmState::Snapshot(),
+                        cmCommandContext const& cc = cmCommandContext())
+      : Context(cc), Snapshot(snapshot)
     {
     }
 
-    void Append(cmListFileContext const& context);
-
     void PrintTitle(std::ostream& out);
     void PrintCallStack(std::ostream& out);
   private:
+    cmCommandContext Context;
     cmState::Snapshot Snapshot;
 };
 

+ 1 - 1
Source/cmMacroCommand.cxx

@@ -97,6 +97,7 @@ bool cmMacroHelperCommand::InvokeInitialPass
     }
 
   cmMakefile::MacroPushPop macroScope(this->Makefile,
+                                      this->FilePath,
                                       this->Policies);
 
   // set the value of argc
@@ -131,7 +132,6 @@ bool cmMacroHelperCommand::InvokeInitialPass
     newLFF.Arguments.clear();
     newLFF.Arguments.reserve(this->Functions[c].Arguments.size());
     newLFF.Name = this->Functions[c].Name;
-    newLFF.FilePath = this->Functions[c].FilePath;
     newLFF.Line = this->Functions[c].Line;
 
     // for each argument of the current function

+ 113 - 30
Source/cmMakefile.cxx

@@ -247,11 +247,11 @@ void cmMakefile::IssueMessage(cmake::MessageType t,
                               std::string const& text) const
 {
   // Collect context information.
-  if(!this->CallStack.empty())
+  if(!this->ExecutionStatusStack.empty())
     {
     if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR))
       {
-      this->CallStack.back().Status->SetNestedError(true);
+      this->ExecutionStatusStack.back()->SetNestedError(true);
       }
     this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace());
     }
@@ -275,33 +275,29 @@ void cmMakefile::IssueMessage(cmake::MessageType t,
 //----------------------------------------------------------------------------
 cmListFileBacktrace cmMakefile::GetBacktrace() const
 {
-  cmListFileBacktrace backtrace(this->StateSnapshot);
-  for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
-      i != this->CallStack.rend(); ++i)
+  cmListFileBacktrace backtrace;
+  if (!this->ContextStack.empty())
     {
-    backtrace.Append(*i->Context);
+    backtrace = cmListFileBacktrace(this->StateSnapshot,
+                                    *this->ContextStack.back());
     }
   return backtrace;
 }
 
 //----------------------------------------------------------------------------
 cmListFileBacktrace
-cmMakefile::GetBacktrace(cmListFileContext const& lfc) const
+cmMakefile::GetBacktrace(cmCommandContext const& cc) const
 {
-  cmListFileBacktrace backtrace(this->StateSnapshot);
-  backtrace.Append(lfc);
-  for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
-      i != this->CallStack.rend(); ++i)
-    {
-    backtrace.Append(*i->Context);
-    }
-  return backtrace;
+  cmState::Snapshot snp = this->StateSnapshot;
+  return cmListFileBacktrace(snp, cc);
 }
 
 //----------------------------------------------------------------------------
 cmListFileContext cmMakefile::GetExecutionContext() const
 {
-  return *this->CallStack.back().Context;
+  return cmListFileContext::FromCommandContext(
+        *this->ContextStack.back(),
+        this->StateSnapshot.GetExecutionListFile());
 }
 
 //----------------------------------------------------------------------------
@@ -461,11 +457,22 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf,
   this->Makefile->PushPolicyBarrier();
   this->Makefile->ListFileStack.push_back(filenametoread);
   this->Makefile->PushFunctionBlockerBarrier();
+
+  this->Makefile->StateSnapshot =
+      this->Makefile->GetState()->CreateCallStackSnapshot(
+        this->Makefile->StateSnapshot,
+        this->Makefile->ContextStack.back()->Name,
+        this->Makefile->ContextStack.back()->Line,
+        filenametoread);
 }
 
 //----------------------------------------------------------------------------
 cmMakefile::IncludeScope::~IncludeScope()
 {
+  this->Makefile->StateSnapshot =
+      this->Makefile->GetState()->Pop(this->Makefile->StateSnapshot);
+  assert(this->Makefile->StateSnapshot.IsValid());
+
   this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
   // Enforce matching policy scopes inside the included file.
   this->Makefile->PopPolicyBarrier(this->ReportError);
@@ -534,6 +541,25 @@ void cmMakefile::IncludeScope::EnforceCMP0011()
     }
 }
 
+class cmParseFileScope
+{
+public:
+  cmParseFileScope(cmMakefile* mf)
+    : Makefile(mf)
+  {
+    this->Makefile->ContextStack.push_back(&this->Context);
+  }
+
+  ~cmParseFileScope()
+  {
+    this->Makefile->ContextStack.pop_back();
+  }
+
+private:
+  cmMakefile* Makefile;
+  cmCommandContext Context;
+};
+
 bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope)
 {
   this->AddDefinition("CMAKE_PARENT_LIST_FILE",
@@ -545,10 +571,14 @@ bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope)
   IncludeScope incScope(this, filenametoread, noPolicyScope);
 
   cmListFile listFile;
+  {
+  cmParseFileScope pfs(this);
   if (!listFile.ParseFile(filenametoread.c_str(), false, this))
     {
     return false;
     }
+  }
+
   this->ReadListFile(listFile, filenametoread);
   if(cmSystemTools::GetFatalErrorOccured())
     {
@@ -565,11 +595,27 @@ public:
   {
     this->Makefile->ListFileStack.push_back(filenametoread);
     this->Makefile->PushPolicyBarrier();
+
+    long line = 0;
+    std::string name;
+    if (!this->Makefile->ContextStack.empty())
+      {
+      line = this->Makefile->ContextStack.back()->Line;
+      name = this->Makefile->ContextStack.back()->Name;
+      }
+    this->Makefile->StateSnapshot =
+        this->Makefile->GetState()->CreateInlineListFileSnapshot(
+          this->Makefile->StateSnapshot, name, line, filenametoread);
+    assert(this->Makefile->StateSnapshot.IsValid());
     this->Makefile->PushFunctionBlockerBarrier();
   }
 
   ~ListFileScope()
   {
+    this->Makefile->StateSnapshot =
+        this->Makefile->GetState()->Pop(this->Makefile->StateSnapshot);
+    assert(this->Makefile->StateSnapshot.IsValid());
+
     this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
     this->Makefile->PopPolicyBarrier(this->ReportError);
     this->Makefile->ListFileStack.pop_back();
@@ -590,10 +636,13 @@ bool cmMakefile::ReadListFile(const char* filename)
   ListFileScope scope(this, filenametoread);
 
   cmListFile listFile;
+  {
+  cmParseFileScope pfs(this);
   if (!listFile.ParseFile(filenametoread.c_str(), false, this))
     {
     return false;
     }
+  }
 
   this->ReadListFile(listFile, filenametoread);
   if(cmSystemTools::GetFatalErrorOccured())
@@ -1571,8 +1620,16 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
   this->ImportedTargets = parent->ImportedTargets;
 }
 
-void cmMakefile::PushFunctionScope(const cmPolicies::PolicyMap& pm)
+void cmMakefile::PushFunctionScope(std::string const& fileName,
+                                   const cmPolicies::PolicyMap& pm)
 {
+  this->StateSnapshot =
+      this->GetState()->CreateFunctionCallSnapshot(
+        this->StateSnapshot,
+        this->ContextStack.back()->Name, this->ContextStack.back()->Line,
+        fileName);
+  assert(this->StateSnapshot.IsValid());
+
   this->Internal->PushDefinitions();
 
   this->PushLoopBlockBarrier();
@@ -1592,6 +1649,9 @@ void cmMakefile::PopFunctionScope(bool reportError)
   this->PopPolicyBarrier(reportError);
   this->PopPolicy();
 
+  this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot);
+  assert(this->StateSnapshot.IsValid());
+
   this->PopFunctionBlockerBarrier(reportError);
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -1605,8 +1665,16 @@ void cmMakefile::PopFunctionScope(bool reportError)
   this->Internal->PopDefinitions();
 }
 
-void cmMakefile::PushMacroScope(const cmPolicies::PolicyMap& pm)
+void cmMakefile::PushMacroScope(std::string const& fileName,
+                                const cmPolicies::PolicyMap& pm)
 {
+  this->StateSnapshot =
+      this->GetState()->CreateMacroCallSnapshot(
+        this->StateSnapshot,
+        this->ContextStack.back()->Name, this->ContextStack.back()->Line,
+        fileName);
+  assert(this->StateSnapshot.IsValid());
+
   this->PushFunctionBlockerBarrier();
 
   this->PushPolicy(true, pm);
@@ -1618,6 +1686,9 @@ void cmMakefile::PopMacroScope(bool reportError)
   this->PopPolicyBarrier(reportError);
   this->PopPolicy();
 
+  this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot);
+  assert(this->StateSnapshot.IsValid());
+
   this->PopFunctionBlockerBarrier(reportError);
 }
 
@@ -1635,6 +1706,7 @@ public:
     std::string currentStart =
         this->Makefile->StateSnapshot.GetCurrentSourceDirectory();
     currentStart += "/CMakeLists.txt";
+    this->Makefile->StateSnapshot.SetListFile(currentStart);
     this->Makefile->ListFileStack.push_back(currentStart);
     this->Makefile->PushPolicyBarrier();
     this->Makefile->PushFunctionBlockerBarrier();
@@ -1686,11 +1758,14 @@ void cmMakefile::Configure()
   this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart.c_str());
 
   cmListFile listFile;
+  {
+  cmParseFileScope pfs(this);
   if (!listFile.ParseFile(currentStart.c_str(), this->IsRootMakefile(), this))
     {
     this->SetConfigured();
     return;
     }
+  }
   this->ReadListFile(listFile, currentStart);
   if(cmSystemTools::GetFatalErrorOccured())
     {
@@ -1778,7 +1853,9 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
     }
 
   cmState::Snapshot newSnapshot = this->GetState()
-      ->CreateBuildsystemDirectorySnapshot(this->StateSnapshot);
+      ->CreateBuildsystemDirectorySnapshot(this->StateSnapshot,
+                                           this->ContextStack.back()->Name,
+                                           this->ContextStack.back()->Line);
 
   // create a new local generator and set its parent
   cmLocalGenerator *lg2 = this->GetGlobalGenerator()
@@ -1996,7 +2073,7 @@ void cmMakefile::LogUnused(const char* reason,
     {
     std::string path;
     cmListFileContext lfc;
-    if (!this->CallStack.empty())
+    if (!this->ExecutionStatusStack.empty())
       {
       lfc = this->GetExecutionContext();
       path = lfc.FilePath;
@@ -3360,11 +3437,12 @@ bool cmMakefile::IsLoopBlock() const
 
 std::string cmMakefile::GetExecutionFilePath() const
 {
-  if (this->CallStack.empty())
+  if (this->ContextStack.empty())
     {
     return std::string();
     }
-  return this->CallStack.back().Context->FilePath;
+  assert(this->StateSnapshot.IsValid());
+  return this->StateSnapshot.GetExecutionListFile();
 }
 
 //----------------------------------------------------------------------------
@@ -3455,7 +3533,7 @@ bool cmMakefile::ExpandArguments(
 //----------------------------------------------------------------------------
 void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb)
 {
-  if(!this->CallStack.empty())
+  if(!this->ExecutionStatusStack.empty())
     {
     // Record the context in which the blocker is created.
     fb->SetStartingContext(this->GetExecutionContext());
@@ -3488,11 +3566,13 @@ cmMakefile::RemoveFunctionBlocker(cmFunctionBlocker* fb,
       if(!(*pos)->ShouldRemove(lff, *this))
         {
         cmListFileContext const& lfc = fb->GetStartingContext();
+        cmListFileContext closingContext =
+            cmListFileContext::FromCommandContext(lff, lfc.FilePath);
         std::ostringstream e;
         e << "A logical block opening on the line\n"
           << "  " << lfc << "\n"
           << "closes on the line\n"
-          << "  " << lff << "\n"
+          << "  " << closingContext << "\n"
           << "with mis-matching arguments.";
         this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
         }
@@ -5476,10 +5556,11 @@ AddRequiredTargetCFeature(cmTarget *target, const std::string& feature) const
 
 
 cmMakefile::FunctionPushPop::FunctionPushPop(cmMakefile* mf,
+                                             const std::string& fileName,
                                              cmPolicies::PolicyMap const& pm)
   : Makefile(mf), ReportError(true)
 {
-  this->Makefile->PushFunctionScope(pm);
+  this->Makefile->PushFunctionScope(fileName, pm);
 }
 
 cmMakefile::FunctionPushPop::~FunctionPushPop()
@@ -5489,10 +5570,11 @@ cmMakefile::FunctionPushPop::~FunctionPushPop()
 
 
 cmMakefile::MacroPushPop::MacroPushPop(cmMakefile* mf,
+                                       const std::string& fileName,
                                        const cmPolicies::PolicyMap& pm)
   : Makefile(mf), ReportError(true)
 {
-  this->Makefile->PushMacroScope(pm);
+  this->Makefile->PushMacroScope(fileName, pm);
 }
 
 cmMakefile::MacroPushPop::~MacroPushPop()
@@ -5500,14 +5582,15 @@ cmMakefile::MacroPushPop::~MacroPushPop()
   this->Makefile->PopMacroScope(this->ReportError);
 }
 
-cmMakefileCall::cmMakefileCall(cmMakefile* mf, const cmListFileContext& lfc,
+cmMakefileCall::cmMakefileCall(cmMakefile* mf, const cmCommandContext& lfc,
                                cmExecutionStatus& status): Makefile(mf)
 {
-  cmMakefile::CallStackEntry entry = {&lfc, &status};
-  this->Makefile->CallStack.push_back(entry);
+  this->Makefile->ContextStack.push_back(&lfc);
+  this->Makefile->ExecutionStatusStack.push_back(&status);
 }
 
 cmMakefileCall::~cmMakefileCall()
 {
-  this->Makefile->CallStack.pop_back();
+  this->Makefile->ExecutionStatusStack.pop_back();
+  this->Makefile->ContextStack.pop_back();
 }

+ 12 - 15
Source/cmMakefile.h

@@ -547,7 +547,7 @@ public:
    * Get the current context backtrace.
    */
   cmListFileBacktrace GetBacktrace() const;
-  cmListFileBacktrace GetBacktrace(cmListFileContext const& lfc) const;
+  cmListFileBacktrace GetBacktrace(cmCommandContext const& lfc) const;
   cmListFileContext GetExecutionContext() const;
 
   /**
@@ -720,7 +720,7 @@ public:
   class FunctionPushPop
   {
   public:
-    FunctionPushPop(cmMakefile* mf,
+    FunctionPushPop(cmMakefile* mf, std::string const& fileName,
                     cmPolicies::PolicyMap const& pm);
     ~FunctionPushPop();
 
@@ -733,8 +733,8 @@ public:
   class MacroPushPop
   {
   public:
-    MacroPushPop(cmMakefile* mf,
-                    cmPolicies::PolicyMap const& pm);
+    MacroPushPop(cmMakefile* mf, std::string const& fileName,
+                 cmPolicies::PolicyMap const& pm);
     ~MacroPushPop();
 
     void Quiet() { this->ReportError = false; }
@@ -743,9 +743,11 @@ public:
     bool ReportError;
   };
 
-  void PushFunctionScope(cmPolicies::PolicyMap const& pm);
+  void PushFunctionScope(std::string const& fileName,
+                         cmPolicies::PolicyMap const& pm);
   void PopFunctionScope(bool reportError);
-  void PushMacroScope(cmPolicies::PolicyMap const& pm);
+  void PushMacroScope(std::string const& fileName,
+                      cmPolicies::PolicyMap const& pm);
   void PopMacroScope(bool reportError);
   void PushScope();
   void PopScope();
@@ -935,15 +937,10 @@ private:
   // stack of list files being read
   std::vector<std::string> ListFileStack;
 
-  // stack of commands being invoked.
-  struct CallStackEntry
-  {
-    cmListFileContext const* Context;
-    cmExecutionStatus* Status;
-  };
-  typedef std::vector<CallStackEntry> CallStackType;
-  CallStackType CallStack;
+  std::vector<cmCommandContext const*> ContextStack;
+  std::vector<cmExecutionStatus*> ExecutionStatusStack;
   friend class cmMakefileCall;
+  friend class cmParseFileScope;
 
   std::vector<cmTarget*> ImportedTargetsOwned;
   TargetMap ImportedTargets;
@@ -1058,7 +1055,7 @@ class cmMakefileCall
 {
 public:
   cmMakefileCall(cmMakefile* mf,
-                 cmListFileContext const& lfc,
+                 cmCommandContext const& lfc,
                  cmExecutionStatus& status);
   ~cmMakefileCall();
 private:

+ 139 - 1
Source/cmState.cxx

@@ -20,10 +20,14 @@
 
 struct cmState::SnapshotDataType
 {
+  cmState::PositionType CallStackParent;
   cmState::PositionType DirectoryParent;
   cmState::SnapshotType SnapshotType;
+  cmLinkedTree<std::string>::iterator ExecutionListFile;
   cmLinkedTree<cmState::BuildsystemDirectoryStateType>::iterator
                                                           BuildSystemDirectory;
+  std::string EntryPointCommand;
+  long EntryPointLine;
 };
 
 struct cmState::BuildsystemDirectoryStateType
@@ -226,6 +230,7 @@ cmState::Snapshot cmState::Reset()
 
   this->BuildsystemDirectory.Truncate();
   PositionType pos = this->SnapshotData.Truncate();
+  this->ExecutionListFiles.Truncate();
 
   this->DefineProperty
     ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY,
@@ -682,22 +687,113 @@ cmState::Snapshot cmState::CreateBaseSnapshot()
   pos->SnapshotType = BuildsystemDirectoryType;
   pos->BuildSystemDirectory =
       this->BuildsystemDirectory.Extend(this->BuildsystemDirectory.Root());
+  pos->ExecutionListFile =
+      this->ExecutionListFiles.Extend(this->ExecutionListFiles.Root());
   return cmState::Snapshot(this, pos);
 }
 
 cmState::Snapshot
-cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot)
+cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot,
+                                    std::string const& entryPointCommand,
+                                    long entryPointLine)
 {
   assert(originSnapshot.IsValid());
   PositionType pos = this->SnapshotData.Extend(originSnapshot.Position);
+  pos->CallStackParent = originSnapshot.Position;
+  pos->EntryPointLine = entryPointLine;
+  pos->EntryPointCommand = entryPointCommand;
   pos->DirectoryParent = originSnapshot.Position;
   pos->SnapshotType = BuildsystemDirectoryType;
   pos->BuildSystemDirectory =
       this->BuildsystemDirectory.Extend(
         originSnapshot.Position->BuildSystemDirectory);
+  pos->ExecutionListFile =
+      this->ExecutionListFiles.Extend(
+        originSnapshot.Position->ExecutionListFile);
   return cmState::Snapshot(this, pos);
 }
 
+cmState::Snapshot
+cmState::CreateFunctionCallSnapshot(cmState::Snapshot originSnapshot,
+                                    std::string const& entryPointCommand,
+                                    long entryPointLine,
+                                    std::string const& fileName)
+{
+  PositionType pos = this->SnapshotData.Extend(originSnapshot.Position,
+                                               *originSnapshot.Position);
+  pos->CallStackParent = originSnapshot.Position;
+  pos->EntryPointLine = entryPointLine;
+  pos->EntryPointCommand = entryPointCommand;
+  pos->SnapshotType = FunctionCallType;
+  pos->ExecutionListFile = this->ExecutionListFiles.Extend(
+        originSnapshot.Position->ExecutionListFile, fileName);
+  return cmState::Snapshot(this, pos);
+}
+
+
+cmState::Snapshot
+cmState::CreateMacroCallSnapshot(cmState::Snapshot originSnapshot,
+                                    std::string const& entryPointCommand,
+                                    long entryPointLine,
+                                    std::string const& fileName)
+{
+  PositionType pos = this->SnapshotData.Extend(originSnapshot.Position,
+                                               *originSnapshot.Position);
+  pos->CallStackParent = originSnapshot.Position;
+  pos->EntryPointLine = entryPointLine;
+  pos->EntryPointCommand = entryPointCommand;
+  pos->SnapshotType = MacroCallType;
+  pos->ExecutionListFile = this->ExecutionListFiles.Extend(
+        originSnapshot.Position->ExecutionListFile, fileName);
+  return cmState::Snapshot(this, pos);
+}
+
+cmState::Snapshot
+cmState::CreateCallStackSnapshot(cmState::Snapshot originSnapshot,
+                                 const std::string& entryPointCommand,
+                                 long entryPointLine,
+                                 const std::string& fileName)
+{
+  PositionType pos = this->SnapshotData.Extend(originSnapshot.Position,
+                                               *originSnapshot.Position);
+  pos->CallStackParent = originSnapshot.Position;
+  pos->EntryPointLine = entryPointLine;
+  pos->EntryPointCommand = entryPointCommand;
+  pos->SnapshotType = CallStackType;
+  pos->ExecutionListFile = this->ExecutionListFiles.Extend(
+        originSnapshot.Position->ExecutionListFile, fileName);
+  return cmState::Snapshot(this, pos);
+}
+
+cmState::Snapshot
+cmState::CreateInlineListFileSnapshot(cmState::Snapshot originSnapshot,
+                                      const std::string& entryPointCommand,
+                                      long entryPointLine,
+                                      const std::string& fileName)
+{
+  PositionType pos = this->SnapshotData.Extend(originSnapshot.Position,
+                                               *originSnapshot.Position);
+  pos->CallStackParent = originSnapshot.Position;
+  pos->EntryPointLine = entryPointLine;
+  pos->EntryPointCommand = entryPointCommand;
+  pos->SnapshotType = InlineListFileType;
+  pos->ExecutionListFile = this->ExecutionListFiles.Extend(
+        originSnapshot.Position->ExecutionListFile, fileName);
+  return cmState::Snapshot(this, pos);
+}
+
+cmState::Snapshot cmState::Pop(cmState::Snapshot originSnapshot)
+{
+  PositionType pos = originSnapshot.Position;
+  PositionType prevPos = pos;
+  ++prevPos;
+  if (prevPos == this->SnapshotData.Root())
+    {
+    return Snapshot(this, prevPos);
+    }
+  return Snapshot(this, originSnapshot.Position->CallStackParent);
+}
+
 cmState::Snapshot::Snapshot(cmState* state, PositionType position)
   : State(state),
   Position(position)
@@ -742,6 +838,11 @@ void cmState::Snapshot::SetCurrentBinaryDirectory(std::string const& dir)
   this->ComputeRelativePathTopBinary();
 }
 
+void cmState::Snapshot::SetListFile(const std::string& listfile)
+{
+  *this->Position->ExecutionListFile = listfile;
+}
+
 std::vector<std::string> const&
 cmState::Snapshot::GetCurrentSourceDirectoryComponents() const
 {
@@ -776,6 +877,21 @@ void cmState::Snapshot::SetRelativePathTopBinary(const char* dir)
   this->Position->BuildSystemDirectory->RelativePathTopBinary = dir;
 }
 
+std::string cmState::Snapshot::GetExecutionListFile() const
+{
+  return *this->Position->ExecutionListFile;
+}
+
+std::string cmState::Snapshot::GetEntryPointCommand() const
+{
+  return this->Position->EntryPointCommand;
+}
+
+long cmState::Snapshot::GetEntryPointLine() const
+{
+  return this->Position->EntryPointLine;
+}
+
 bool cmState::Snapshot::IsValid() const
 {
   return this->State && this->Position.IsValid()
@@ -799,6 +915,28 @@ cmState::Snapshot cmState::Snapshot::GetBuildsystemDirectoryParent() const
   return snapshot;
 }
 
+cmState::Snapshot cmState::Snapshot::GetCallStackParent() const
+{
+  assert(this->State);
+  assert(this->Position != this->State->SnapshotData.Root());
+
+  Snapshot snapshot;
+  if (this->Position->SnapshotType == cmState::BuildsystemDirectoryType)
+    {
+    return snapshot;
+    }
+
+  PositionType parentPos = this->Position;
+  ++parentPos;
+  if (parentPos == this->State->SnapshotData.Root())
+    {
+    return snapshot;
+    }
+
+  snapshot = Snapshot(this->State, parentPos);
+  return snapshot;
+}
+
 cmState* cmState::Snapshot::GetState() const
 {
   return this->State;

+ 35 - 2
Source/cmState.h

@@ -31,7 +31,11 @@ public:
 
   enum SnapshotType
   {
-    BuildsystemDirectoryType
+    BuildsystemDirectoryType,
+    FunctionCallType,
+    MacroCallType,
+    CallStackType,
+    InlineListFileType
   };
 
   class Snapshot {
@@ -43,6 +47,8 @@ public:
     const char* GetCurrentBinaryDirectory() const;
     void SetCurrentBinaryDirectory(std::string const& dir);
 
+    void SetListFile(std::string const& listfile);
+
     std::vector<std::string> const&
     GetCurrentSourceDirectoryComponents() const;
     std::vector<std::string> const&
@@ -53,8 +59,13 @@ public:
     void SetRelativePathTopSource(const char* dir);
     void SetRelativePathTopBinary(const char* dir);
 
+    std::string GetExecutionListFile() const;
+    std::string GetEntryPointCommand() const;
+    long GetEntryPointLine() const;
+
     bool IsValid() const;
     Snapshot GetBuildsystemDirectoryParent() const;
+    Snapshot GetCallStackParent() const;
 
     cmState* GetState() const;
 
@@ -69,7 +80,27 @@ public:
   };
 
   Snapshot CreateBaseSnapshot();
-  Snapshot CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot);
+  Snapshot
+  CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot,
+                                     std::string const& entryPointCommand,
+                                     long entryPointLine);
+  Snapshot CreateFunctionCallSnapshot(Snapshot originSnapshot,
+                                      std::string const& entryPointCommand,
+                                      long entryPointLine,
+                                      std::string const& fileName);
+  Snapshot CreateMacroCallSnapshot(Snapshot originSnapshot,
+                                   std::string const& entryPointCommand,
+                                   long entryPointLine,
+                                   std::string const& fileName);
+  Snapshot CreateCallStackSnapshot(Snapshot originSnapshot,
+                                   std::string const& entryPointCommand,
+                                   long entryPointLine,
+                                   std::string const& fileName);
+  Snapshot CreateInlineListFileSnapshot(Snapshot originSnapshot,
+                                        const std::string& entryPointCommand,
+                                        long entryPointLine,
+                                        std::string const& fileName);
+  Snapshot Pop(Snapshot originSnapshot);
 
   enum CacheEntryType{ BOOL=0, PATH, FILEPATH, STRING, INTERNAL,STATIC,
                        UNINITIALIZED };
@@ -175,6 +206,8 @@ private:
   struct BuildsystemDirectoryStateType;
   cmLinkedTree<BuildsystemDirectoryStateType> BuildsystemDirectory;
 
+  cmLinkedTree<std::string> ExecutionListFiles;
+
   cmLinkedTree<SnapshotDataType> SnapshotData;
 
   std::vector<std::string> SourceDirectoryComponents;

+ 0 - 1
Source/cmVariableWatchCommand.cxx

@@ -63,7 +63,6 @@ static void cmVariableWatchCommandVariableAccessed(
       cmListFileArgument(stack, cmListFileArgument::Quoted,
                          9999));
     newLFF.Name = data->Command;
-    newLFF.FilePath = "unknown";
     newLFF.Line = 9999;
     cmExecutionStatus status;
     if(!makefile->ExecuteCommand(newLFF,status))

+ 3 - 1
Tests/RunCMake/Syntax/BOM-UTF-16-BE-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BOM-UTF-16-BE.cmake:
   File
 
     .*/Tests/RunCMake/Syntax/BOM-UTF-16-BE.cmake
 
   starts with a Byte-Order-Mark that is not UTF-8.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/BOM-UTF-16-LE-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BOM-UTF-16-LE.cmake:
   File
 
     .*/Tests/RunCMake/Syntax/BOM-UTF-16-LE.cmake
 
   starts with a Byte-Order-Mark that is not UTF-8.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/BOM-UTF-32-BE-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BOM-UTF-32-BE.cmake:
   File
 
     .*/Tests/RunCMake/Syntax/BOM-UTF-32-BE.cmake
 
   starts with a Byte-Order-Mark that is not UTF-8.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/BOM-UTF-32-LE-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BOM-UTF-32-LE.cmake:
   File
 
     .*/Tests/RunCMake/Syntax/BOM-UTF-32-LE.cmake
 
   starts with a Byte-Order-Mark that is not UTF-8.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/BracketNoSpace0-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BracketNoSpace0.cmake:
   Syntax Error in cmake code at
 
     .*/Tests/RunCMake/Syntax/BracketNoSpace0.cmake:1:27
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/BracketNoSpace1-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BracketNoSpace1.cmake:
   Syntax Error in cmake code at
 
     .*/Tests/RunCMake/Syntax/BracketNoSpace1.cmake:1:24
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/BracketNoSpace2-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BracketNoSpace2.cmake:
   Syntax Error in cmake code at
 
     .*/Tests/RunCMake/Syntax/BracketNoSpace2.cmake:1:44
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/BracketNoSpace3-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BracketNoSpace3.cmake:
   Syntax Error in cmake code at
 
     .*/Tests/RunCMake/Syntax/BracketNoSpace3.cmake:1:45
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/BracketNoSpace4-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BracketNoSpace4.cmake:
   Syntax Error in cmake code at
 
     .*/Tests/RunCMake/Syntax/BracketNoSpace4.cmake:1:44
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/BracketNoSpace5-stderr.txt

@@ -1,6 +1,8 @@
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in BracketNoSpace5.cmake:
   Syntax Error in cmake code at
 
     .*/Tests/RunCMake/Syntax/BracketNoSpace5.cmake:1:45
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 3 - 1
Tests/RunCMake/Syntax/ParenInENV-stderr.txt

@@ -1,9 +1,11 @@
-CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+CMake Warning \(dev\) in ParenInENV.cmake:
   Syntax Warning in cmake code at
 
     .*/Tests/RunCMake/Syntax/ParenInENV.cmake:2:21
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
 This warning is for project developers.  Use -Wno-dev to suppress it.
 
 CMake Error at ParenInENV.cmake:2 \(message\):

+ 9 - 3
Tests/RunCMake/Syntax/ParenNoSpace1-stderr.txt

@@ -1,22 +1,28 @@
-CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+CMake Warning \(dev\) in ParenNoSpace1.cmake:
   Syntax Warning in cmake code at
 
     .*/Tests/RunCMake/Syntax/ParenNoSpace1.cmake:1:26
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
 This warning is for project developers.  Use -Wno-dev to suppress it.
 
-CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+CMake Warning \(dev\) in ParenNoSpace1.cmake:
   Syntax Warning in cmake code at
 
     .*/Tests/RunCMake/Syntax/ParenNoSpace1.cmake:2:26
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
 This warning is for project developers.  Use -Wno-dev to suppress it.
 
-CMake Error at CMakeLists.txt:3 \(include\):
+CMake Error in ParenNoSpace1.cmake:
   Syntax Error in cmake code at
 
     .*/Tests/RunCMake/Syntax/ParenNoSpace1.cmake:3:29
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 6 - 2
Tests/RunCMake/Syntax/StringNoSpace-stderr.txt

@@ -1,17 +1,21 @@
-CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+CMake Warning \(dev\) in StringNoSpace.cmake:
   Syntax Warning in cmake code at
 
     .*/Tests/RunCMake/Syntax/StringNoSpace.cmake:2:28
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
 This warning is for project developers.  Use -Wno-dev to suppress it.
 
-CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+CMake Warning \(dev\) in StringNoSpace.cmake:
   Syntax Warning in cmake code at
 
     .*/Tests/RunCMake/Syntax/StringNoSpace.cmake:2:31
 
   Argument not separated from preceding token by whitespace.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
 This warning is for project developers.  Use -Wno-dev to suppress it.
 
 \[1 \${var} \\n 4\]