Browse Source

Merge topic 'command-refactoring3'

dfaa87f1b3 cmState: Support BuiltinCommands as free functions
28f2d12a05 cmCommand: De-virtualize function InvokeInitialPass
de77d355ac cmState: Add scripted commands by value
0101ace131 cmUnexpectedCommand: Replace with lambda expression
015001aaf1 cmState: Hold commands by value
1eebc29563 cmCommand: deprecate functions GetMakefile and SetError

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3574
Brad King 6 years ago
parent
commit
6f476a4169

+ 0 - 2
Source/CMakeLists.txt

@@ -662,8 +662,6 @@ set(SRCS
   cmTryCompileCommand.h
   cmTryRunCommand.cxx
   cmTryRunCommand.h
-  cmUnexpectedCommand.cxx
-  cmUnexpectedCommand.h
   cmUnsetCommand.cxx
   cmUnsetCommand.h
   cmUseMangledMesaCommand.cxx

+ 8 - 9
Source/CTest/cmCTestHandlerCommand.cxx

@@ -4,6 +4,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestGenericHandler.h"
+#include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmSystemTools.h"
@@ -13,8 +14,6 @@
 #include <sstream>
 #include <stdlib.h>
 
-class cmExecutionStatus;
-
 cmCTestHandlerCommand::cmCTestHandlerCommand()
 {
   const size_t INIT_SIZE = 100;
@@ -86,7 +85,7 @@ private:
 }
 
 bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
-                                        cmExecutionStatus& /*unused*/)
+                                        cmExecutionStatus& status)
 {
   // save error state and restore it if needed
   SaveRestoreErrorState errorState;
@@ -126,7 +125,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
     if (capureCMakeError) {
       this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                     "-1");
-      std::string const err = this->GetName() + " " + this->GetError();
+      std::string const err = this->GetName() + " " + status.GetError();
       if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
         cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
       }
@@ -195,8 +194,8 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
     if (capureCMakeError) {
       this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                     "-1");
-      const char* err = this->GetError();
-      if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
+      std::string const& err = status.GetError();
+      if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
         cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
       }
       return true;
@@ -220,7 +219,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
       this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                     "-1");
       cmCTestLog(this->CTest, ERROR_MESSAGE,
-                 this->GetName() << " " << this->GetError() << "\n");
+                 this->GetName() << " " << status.GetError() << "\n");
       // return success because failure is recorded in CAPTURE_CMAKE_ERROR
       return true;
     }
@@ -240,10 +239,10 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
     const char* returnString = "0";
     if (cmSystemTools::GetErrorOccuredFlag()) {
       returnString = "-1";
-      const char* err = this->GetError();
+      std::string const& err = status.GetError();
       // print out the error if it is not "unknown error" which means
       // there was no message
-      if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
+      if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
         cmCTestLog(this->CTest, ERROR_MESSAGE, err);
       }
     }

+ 1 - 1
Source/cmCPluginAPI.cxx

@@ -421,7 +421,7 @@ int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs,
     // Assume all arguments are quoted.
     lff.Arguments.emplace_back(args[i], cmListFileArgument::Quoted, 0);
   }
-  cmExecutionStatus status;
+  cmExecutionStatus status(*mf);
   return mf->ExecuteCommand(lff, status);
 }
 

+ 34 - 8
Source/cmCommand.cxx

@@ -2,11 +2,19 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCommand.h"
 
+#include <utility>
+
+#include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 
-class cmExecutionStatus;
 struct cmListFileArgument;
 
+void cmCommand::SetExecutionStatus(cmExecutionStatus* status)
+{
+  this->Status = status;
+  this->Makefile = &status->GetMakefile();
+}
+
 bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
                                   cmExecutionStatus& status)
 {
@@ -19,15 +27,33 @@ bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
   return this->InitialPass(expandedArguments, status);
 }
 
-const char* cmCommand::GetError()
+void cmCommand::SetError(const std::string& e)
 {
-  if (this->Error.empty()) {
-    return "unknown error.";
-  }
-  return this->Error.c_str();
+  this->Status->SetError(e);
 }
 
-void cmCommand::SetError(const std::string& e)
+cmLegacyCommandWrapper::cmLegacyCommandWrapper(std::unique_ptr<cmCommand> cmd)
+  : Command(std::move(cmd))
+{
+}
+
+cmLegacyCommandWrapper::cmLegacyCommandWrapper(
+  cmLegacyCommandWrapper const& other)
+  : Command(other.Command->Clone())
+{
+}
+
+cmLegacyCommandWrapper& cmLegacyCommandWrapper::operator=(
+  cmLegacyCommandWrapper const& other)
+{
+  this->Command = other.Command->Clone();
+  return *this;
+}
+
+bool cmLegacyCommandWrapper::operator()(
+  std::vector<cmListFileArgument> const& args, cmExecutionStatus& status) const
 {
-  this->Error = e;
+  auto cmd = this->Command->Clone();
+  cmd->SetExecutionStatus(&status);
+  return cmd->InvokeInitialPass(args, status);
 }

+ 24 - 9
Source/cmCommand.h

@@ -42,16 +42,18 @@ public:
   /**
    * Specify the makefile.
    */
-  void SetMakefile(cmMakefile* m) { this->Makefile = m; }
   cmMakefile* GetMakefile() { return this->Makefile; }
 
+  void SetExecutionStatus(cmExecutionStatus* s);
+  cmExecutionStatus* GetExecutionStatus() { return this->Status; };
+
   /**
    * This is called by the cmMakefile when the command is first
    * encountered in the CMakeLists.txt file.  It expands the command's
    * arguments and then invokes the InitialPass.
    */
-  virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                                 cmExecutionStatus& status);
+  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
+                         cmExecutionStatus& status);
 
   /**
    * This is called when the command is first encountered in
@@ -65,11 +67,6 @@ public:
    */
   virtual std::unique_ptr<cmCommand> Clone() = 0;
 
-  /**
-   * Return the last error string.
-   */
-  const char* GetError();
-
   /**
    * Set the error message
    */
@@ -79,7 +76,25 @@ protected:
   cmMakefile* Makefile = nullptr;
 
 private:
-  std::string Error;
+  cmExecutionStatus* Status = nullptr;
+};
+
+class cmLegacyCommandWrapper
+{
+public:
+  explicit cmLegacyCommandWrapper(std::unique_ptr<cmCommand> cmd);
+
+  cmLegacyCommandWrapper(cmLegacyCommandWrapper const& other);
+  cmLegacyCommandWrapper& operator=(cmLegacyCommandWrapper const& other);
+
+  cmLegacyCommandWrapper(cmLegacyCommandWrapper&&) = default;
+  cmLegacyCommandWrapper& operator=(cmLegacyCommandWrapper&&) = default;
+
+  bool operator()(std::vector<cmListFileArgument> const& args,
+                  cmExecutionStatus& status) const;
+
+private:
+  std::unique_ptr<cmCommand> Command;
 };
 
 #endif

+ 4 - 5
Source/cmCommands.cxx

@@ -147,7 +147,7 @@ void GetScriptingCommands(cmState* state)
                            cm::make_unique<cmGetFilenameComponentCommand>());
   state->AddBuiltinCommand("get_property",
                            cm::make_unique<cmGetPropertyCommand>());
-  state->AddBuiltinCommand("if", cm::make_unique<cmIfCommand>());
+  state->AddBuiltinCommand("if", cmIfCommand);
   state->AddBuiltinCommand("include", cm::make_unique<cmIncludeCommand>());
   state->AddBuiltinCommand("include_guard",
                            cm::make_unique<cmIncludeGuardCommand>());
@@ -162,7 +162,7 @@ void GetScriptingCommands(cmState* state)
   state->AddBuiltinCommand("option", cm::make_unique<cmOptionCommand>());
   state->AddBuiltinCommand("cmake_parse_arguments",
                            cm::make_unique<cmParseArgumentsCommand>());
-  state->AddBuiltinCommand("return", cm::make_unique<cmReturnCommand>());
+  state->AddBuiltinCommand("return", cmReturnCommand);
   state->AddBuiltinCommand("separate_arguments",
                            cm::make_unique<cmSeparateArgumentsCommand>());
   state->AddBuiltinCommand("set", cm::make_unique<cmSetCommand>());
@@ -173,7 +173,7 @@ void GetScriptingCommands(cmState* state)
   state->AddBuiltinCommand("site_name", cm::make_unique<cmSiteNameCommand>());
   state->AddBuiltinCommand("string", cm::make_unique<cmStringCommand>());
   state->AddBuiltinCommand("unset", cm::make_unique<cmUnsetCommand>());
-  state->AddBuiltinCommand("while", cm::make_unique<cmWhileCommand>());
+  state->AddBuiltinCommand("while", cmWhileCommand);
 
   state->AddUnexpectedCommand(
     "else",
@@ -255,8 +255,7 @@ void GetProjectCommands(cmState* state)
                            cm::make_unique<cmDefinePropertyCommand>());
   state->AddBuiltinCommand("enable_language",
                            cm::make_unique<cmEnableLanguageCommand>());
-  state->AddBuiltinCommand("enable_testing",
-                           cm::make_unique<cmEnableTestingCommand>());
+  state->AddBuiltinCommand("enable_testing", cmEnableTestingCommand);
   state->AddBuiltinCommand("get_source_file_property",
                            cm::make_unique<cmGetSourceFilePropertyCommand>());
   state->AddBuiltinCommand("get_target_property",

+ 2 - 2
Source/cmConditionEvaluator.cxx

@@ -4,6 +4,7 @@
 
 #include "cmsys/RegularExpression.hxx"
 #include <algorithm>
+#include <functional>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -17,7 +18,6 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-class cmCommand;
 class cmTest;
 
 static std::string const keyAND = "AND";
@@ -452,7 +452,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
       }
       // does a command exist
       if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) {
-        cmCommand* command =
+        cmState::Command command =
           this->Makefile.GetState()->GetCommand(argP1->c_str());
         this->HandlePredicate(command != nullptr, reducible, arg, newArgs,
                               argP1, argP2);

+ 2 - 4
Source/cmDisallowedCommand.cxx

@@ -24,8 +24,6 @@ bool cmDisallowedCommand::InitialPass(std::vector<std::string> const& args,
       return true;
   }
 
-  this->Command->SetMakefile(this->GetMakefile());
-  bool const ret = this->Command->InitialPass(args, status);
-  this->SetError(this->Command->GetError());
-  return ret;
+  this->Command->SetExecutionStatus(this->GetExecutionStatus());
+  return this->Command->InitialPass(args, status);
 }

+ 4 - 7
Source/cmEnableTestingCommand.cxx

@@ -2,15 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmEnableTestingCommand.h"
 
+#include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 
-class cmExecutionStatus;
-
-// we do this in the final pass so that we now the subdirs have all
-// been defined
-bool cmEnableTestingCommand::InitialPass(std::vector<std::string> const&,
-                                         cmExecutionStatus&)
+bool cmEnableTestingCommand(std::vector<std::string> const&,
+                            cmExecutionStatus& status)
 {
-  this->Makefile->AddDefinition("CMAKE_TESTING_ENABLED", "1");
+  status.GetMakefile().AddDefinition("CMAKE_TESTING_ENABLED", "1");
   return true;
 }

+ 3 - 23
Source/cmEnableTestingCommand.h

@@ -8,13 +8,9 @@
 #include <string>
 #include <vector>
 
-#include "cm_memory.hxx"
-
-#include "cmCommand.h"
-
 class cmExecutionStatus;
 
-/** \class cmEnableTestingCommand
+/**
  * \brief Enable testing for this directory and below.
  *
  * Produce the output testfile. This produces a file in the build directory
@@ -27,23 +23,7 @@ class cmExecutionStatus;
  * Note that CTest expects to find this file in the build directory root;
  * therefore, this command should be in the source directory root too.
  */
-class cmEnableTestingCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  std::unique_ptr<cmCommand> Clone() override
-  {
-    return cm::make_unique<cmEnableTestingCommand>();
-  }
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override;
-};
+bool cmEnableTestingCommand(std::vector<std::string> const&,
+                            cmExecutionStatus&);
 
 #endif

+ 19 - 0
Source/cmExecutionStatus.h

@@ -3,6 +3,11 @@
 #ifndef cmExecutionStatus_h
 #define cmExecutionStatus_h
 
+#include <cmConfigure.h> // IWYU pragma: keep
+#include <string>
+
+class cmMakefile;
+
 /** \class cmExecutionStatus
  * \brief Superclass for all command status classes
  *
@@ -11,14 +16,26 @@
 class cmExecutionStatus
 {
 public:
+  cmExecutionStatus(cmMakefile& makefile)
+    : Makefile(makefile)
+    , Error("unknown error.")
+  {
+  }
+
   void Clear()
   {
+    this->Error = "unknown error.";
     this->ReturnInvoked = false;
     this->BreakInvoked = false;
     this->ContinueInvoked = false;
     this->NestedError = false;
   }
 
+  cmMakefile& GetMakefile() { return this->Makefile; }
+
+  void SetError(std::string const& e) { this->Error = e; }
+  std::string const& GetError() const { return this->Error; }
+
   void SetReturnInvoked() { this->ReturnInvoked = true; }
   bool GetReturnInvoked() const { return this->ReturnInvoked; }
 
@@ -32,6 +49,8 @@ public:
   bool GetNestedError() const { return this->NestedError; }
 
 private:
+  cmMakefile& Makefile;
+  std::string Error;
   bool ReturnInvoked = false;
   bool BreakInvoked = false;
   bool ContinueInvoked = false;

+ 2 - 5
Source/cmFileCopier.cxx

@@ -174,11 +174,8 @@ bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode)
     cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
     for (const auto& arg : items) {
       if (!this->CheckPermissions(arg, **mode)) {
-        std::ostringstream e;
-        e << this->FileCommand->GetError()
-          << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
-             "variable.";
-        this->FileCommand->SetError(e.str());
+        this->FileCommand->SetError(
+          " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.");
         return false;
       }
     }

+ 1 - 1
Source/cmForEachCommand.cxx

@@ -55,7 +55,7 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
         // set the variable to the loop value
         mf.AddDefinition(this->Args[0], arg.c_str());
         // Invoke all the functions that were collected in the block.
-        cmExecutionStatus status;
+        cmExecutionStatus status(mf);
         for (cmListFileFunction const& func : this->Functions) {
           status.Clear();
           mf.ExecuteCommand(func, status);

+ 27 - 47
Source/cmFunctionCommand.cxx

@@ -5,8 +5,6 @@
 #include <sstream>
 #include <utility>
 
-#include "cm_memory.hxx"
-
 #include "cmAlgorithms.h"
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
@@ -15,35 +13,15 @@
 #include "cmState.h"
 
 // define the class for function commands
-class cmFunctionHelperCommand : public cmCommand
+class cmFunctionHelperCommand
 {
 public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  std::unique_ptr<cmCommand> Clone() override
-  {
-    auto newC = cm::make_unique<cmFunctionHelperCommand>();
-    // we must copy when we clone
-    newC->Args = this->Args;
-    newC->Functions = this->Functions;
-    newC->Policies = this->Policies;
-    newC->FilePath = this->FilePath;
-    return std::unique_ptr<cmCommand>(std::move(newC));
-  }
-
   /**
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    */
-  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                         cmExecutionStatus&) override;
-
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override
-  {
-    return false;
-  }
+  bool operator()(std::vector<cmListFileArgument> const& args,
+                  cmExecutionStatus& inStatus) const;
 
   std::vector<std::string> Args;
   std::vector<cmListFileFunction> Functions;
@@ -51,12 +29,15 @@ public:
   std::string FilePath;
 };
 
-bool cmFunctionHelperCommand::InvokeInitialPass(
-  const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
+bool cmFunctionHelperCommand::operator()(
+  std::vector<cmListFileArgument> const& args,
+  cmExecutionStatus& inStatus) const
 {
+  cmMakefile& makefile = inStatus.GetMakefile();
+
   // Expand the argument list to the function.
   std::vector<std::string> expandedArgs;
-  this->Makefile->ExpandArguments(args, expandedArgs);
+  makefile.ExpandArguments(args, expandedArgs);
 
   // make sure the number of arguments passed is at least the number
   // required by the signature
@@ -64,30 +45,30 @@ bool cmFunctionHelperCommand::InvokeInitialPass(
     std::string errorMsg =
       "Function invoked with incorrect arguments for function named: ";
     errorMsg += this->Args[0];
-    this->SetError(errorMsg);
+    inStatus.SetError(errorMsg);
     return false;
   }
 
-  cmMakefile::FunctionPushPop functionScope(this->Makefile, this->FilePath,
+  cmMakefile::FunctionPushPop functionScope(&makefile, this->FilePath,
                                             this->Policies);
 
   // set the value of argc
   std::ostringstream strStream;
   strStream << expandedArgs.size();
-  this->Makefile->AddDefinition("ARGC", strStream.str().c_str());
-  this->Makefile->MarkVariableAsUsed("ARGC");
+  makefile.AddDefinition("ARGC", strStream.str().c_str());
+  makefile.MarkVariableAsUsed("ARGC");
 
   // set the values for ARGV0 ARGV1 ...
   for (unsigned int t = 0; t < expandedArgs.size(); ++t) {
     std::ostringstream tmpStream;
     tmpStream << "ARGV" << t;
-    this->Makefile->AddDefinition(tmpStream.str(), expandedArgs[t].c_str());
-    this->Makefile->MarkVariableAsUsed(tmpStream.str());
+    makefile.AddDefinition(tmpStream.str(), expandedArgs[t].c_str());
+    makefile.MarkVariableAsUsed(tmpStream.str());
   }
 
   // define the formal arguments
   for (unsigned int j = 1; j < this->Args.size(); ++j) {
-    this->Makefile->AddDefinition(this->Args[j], expandedArgs[j - 1].c_str());
+    makefile.AddDefinition(this->Args[j], expandedArgs[j - 1].c_str());
   }
 
   // define ARGV and ARGN
@@ -95,17 +76,16 @@ bool cmFunctionHelperCommand::InvokeInitialPass(
   std::vector<std::string>::const_iterator eit =
     expandedArgs.begin() + (this->Args.size() - 1);
   std::string argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";");
-  this->Makefile->AddDefinition("ARGV", argvDef.c_str());
-  this->Makefile->MarkVariableAsUsed("ARGV");
-  this->Makefile->AddDefinition("ARGN", argnDef.c_str());
-  this->Makefile->MarkVariableAsUsed("ARGN");
+  makefile.AddDefinition("ARGV", argvDef.c_str());
+  makefile.MarkVariableAsUsed("ARGV");
+  makefile.AddDefinition("ARGN", argnDef.c_str());
+  makefile.MarkVariableAsUsed("ARGN");
 
   // Invoke all the functions that were collected in the block.
   // for each function
   for (cmListFileFunction const& func : this->Functions) {
-    cmExecutionStatus status;
-    if (!this->Makefile->ExecuteCommand(func, status) ||
-        status.GetNestedError()) {
+    cmExecutionStatus status(makefile);
+    if (!makefile.ExecuteCommand(func, status) || status.GetNestedError()) {
       // The error message should have already included the call stack
       // so we do not need to report an error here.
       functionScope.Quiet();
@@ -132,11 +112,11 @@ bool cmFunctionFunctionBlocker::IsFunctionBlocked(
     // if this is the endfunction for this function then execute
     if (!this->Depth) {
       // create a new command and add it to cmake
-      auto f = cm::make_unique<cmFunctionHelperCommand>();
-      f->Args = this->Args;
-      f->Functions = this->Functions;
-      f->FilePath = this->GetStartingContext().FilePath;
-      mf.RecordPolicies(f->Policies);
+      cmFunctionHelperCommand f;
+      f.Args = this->Args;
+      f.Functions = this->Functions;
+      f.FilePath = this->GetStartingContext().FilePath;
+      mf.RecordPolicies(f.Policies);
       mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
       // remove the function blocker now that the function is defined
       mf.RemoveFunctionBlocker(this, lff);

+ 10 - 9
Source/cmIfCommand.cxx

@@ -13,6 +13,7 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
+#include <string>
 #include <utility>
 
 static std::string cmIfCommandError(
@@ -47,7 +48,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
       }
 
       // execute the functions for the true parts of the if statement
-      cmExecutionStatus status;
+      cmExecutionStatus status(mf);
       int scopeDepth = 0;
       for (cmListFileFunction const& func : this->Functions) {
         // keep track of scope depth
@@ -176,19 +177,19 @@ bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
 }
 
 //=========================================================================
-bool cmIfCommand::InvokeInitialPass(
-  const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
+bool cmIfCommand(std::vector<cmListFileArgument> const& args,
+                 cmExecutionStatus& inStatus)
 {
+  cmMakefile& makefile = inStatus.GetMakefile();
   std::string errorString;
 
   std::vector<cmExpandedCommandArgument> expandedArguments;
-  this->Makefile->ExpandArguments(args, expandedArguments);
+  makefile.ExpandArguments(args, expandedArguments);
 
   MessageType status;
 
   cmConditionEvaluator conditionEvaluator(
-    *(this->Makefile), this->Makefile->GetExecutionContext(),
-    this->Makefile->GetBacktrace());
+    makefile, makefile.GetExecutionContext(), makefile.GetBacktrace());
 
   bool isTrue =
     conditionEvaluator.IsTrue(expandedArguments, errorString, status);
@@ -197,11 +198,11 @@ bool cmIfCommand::InvokeInitialPass(
     std::string err = "if " + cmIfCommandError(expandedArguments);
     err += errorString;
     if (status == MessageType::FATAL_ERROR) {
-      this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err);
+      makefile.IssueMessage(MessageType::FATAL_ERROR, err);
       cmSystemTools::SetFatalErrorOccured();
       return true;
     }
-    this->Makefile->IssueMessage(status, err);
+    makefile.IssueMessage(status, err);
   }
 
   {
@@ -213,7 +214,7 @@ bool cmIfCommand::InvokeInitialPass(
       fb->HasRun = true;
     }
     fb->Args = args;
-    this->Makefile->AddFunctionBlocker(std::move(fb));
+    makefile.AddFunctionBlocker(std::move(fb));
   }
 
   return true;

+ 2 - 37
Source/cmIfCommand.h

@@ -5,17 +5,12 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <string>
 #include <vector>
 
-#include "cm_memory.hxx"
-
-#include "cmCommand.h"
 #include "cmFunctionBlocker.h"
 #include "cmListFileCache.h"
 
 class cmExecutionStatus;
-class cmExpandedCommandArgument;
 class cmMakefile;
 
 class cmIfFunctionBlocker : public cmFunctionBlocker
@@ -34,37 +29,7 @@ public:
 };
 
 /// Starts an if block
-class cmIfCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  std::unique_ptr<cmCommand> Clone() override
-  {
-    return cm::make_unique<cmIfCommand>();
-  }
-
-  /**
-   * This overrides the default InvokeInitialPass implementation.
-   * It records the arguments before expansion.
-   */
-  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                         cmExecutionStatus&) override;
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override
-  {
-    return false;
-  }
-
-  // Filter the given variable definition based on policy CMP0054.
-  static const char* GetDefinitionIfUnquoted(
-    const cmMakefile* mf, cmExpandedCommandArgument const& argument);
-};
+bool cmIfCommand(std::vector<cmListFileArgument> const& args,
+                 cmExecutionStatus& status);
 
 #endif

+ 2 - 1
Source/cmLoadCommandCommand.cxx

@@ -247,7 +247,8 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
   // function blocker
   if (initFunction) {
     this->Makefile->GetState()->AddScriptedCommand(
-      args[0], cm::make_unique<cmLoadedCommand>(initFunction));
+      args[0],
+      cmLegacyCommandWrapper(cm::make_unique<cmLoadedCommand>(initFunction)));
     return true;
   }
   this->SetError("Attempt to load command failed. "

+ 18 - 36
Source/cmMacroCommand.cxx

@@ -17,35 +17,15 @@
 #include "cmSystemTools.h"
 
 // define the class for macro commands
-class cmMacroHelperCommand : public cmCommand
+class cmMacroHelperCommand
 {
 public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  std::unique_ptr<cmCommand> Clone() override
-  {
-    auto newC = cm::make_unique<cmMacroHelperCommand>();
-    // we must copy when we clone
-    newC->Args = this->Args;
-    newC->Functions = this->Functions;
-    newC->FilePath = this->FilePath;
-    newC->Policies = this->Policies;
-    return std::unique_ptr<cmCommand>(std::move(newC));
-  }
-
   /**
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    */
-  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                         cmExecutionStatus&) override;
-
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override
-  {
-    return false;
-  }
+  bool operator()(std::vector<cmListFileArgument> const& args,
+                  cmExecutionStatus& inStatus) const;
 
   std::vector<std::string> Args;
   std::vector<cmListFileFunction> Functions;
@@ -53,12 +33,15 @@ public:
   std::string FilePath;
 };
 
-bool cmMacroHelperCommand::InvokeInitialPass(
-  const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
+bool cmMacroHelperCommand::operator()(
+  std::vector<cmListFileArgument> const& args,
+  cmExecutionStatus& inStatus) const
 {
+  cmMakefile& makefile = inStatus.GetMakefile();
+
   // Expand the argument list to the macro.
   std::vector<std::string> expandedArgs;
-  this->Makefile->ExpandArguments(args, expandedArgs);
+  makefile.ExpandArguments(args, expandedArgs);
 
   // make sure the number of arguments passed is at least the number
   // required by the signature
@@ -66,11 +49,11 @@ bool cmMacroHelperCommand::InvokeInitialPass(
     std::string errorMsg =
       "Macro invoked with incorrect arguments for macro named: ";
     errorMsg += this->Args[0];
-    this->SetError(errorMsg);
+    inStatus.SetError(errorMsg);
     return false;
   }
 
-  cmMakefile::MacroPushPop macroScope(this->Makefile, this->FilePath,
+  cmMakefile::MacroPushPop macroScope(&makefile, this->FilePath,
                                       this->Policies);
 
   // set the value of argc
@@ -132,9 +115,8 @@ bool cmMacroHelperCommand::InvokeInitialPass(
       arg.Line = k.Line;
       newLFF.Arguments.push_back(std::move(arg));
     }
-    cmExecutionStatus status;
-    if (!this->Makefile->ExecuteCommand(newLFF, status) ||
-        status.GetNestedError()) {
+    cmExecutionStatus status(makefile);
+    if (!makefile.ExecuteCommand(newLFF, status) || status.GetNestedError()) {
       // The error message should have already included the call stack
       // so we do not need to report an error here.
       macroScope.Quiet();
@@ -166,11 +148,11 @@ bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
     if (!this->Depth) {
       mf.AppendProperty("MACROS", this->Args[0].c_str());
       // create a new command and add it to cmake
-      auto f = cm::make_unique<cmMacroHelperCommand>();
-      f->Args = this->Args;
-      f->Functions = this->Functions;
-      f->FilePath = this->GetStartingContext().FilePath;
-      mf.RecordPolicies(f->Policies);
+      cmMacroHelperCommand f;
+      f.Args = this->Args;
+      f.Functions = this->Functions;
+      f.FilePath = this->GetStartingContext().FilePath;
+      mf.RecordPolicies(f.Policies);
       mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
       // remove the function blocker now that the macro is defined
       mf.RemoveFunctionBlocker(this, lff);

+ 4 - 9
Source/cmMakefile.cxx

@@ -16,7 +16,6 @@
 #include <utility>
 
 #include "cmAlgorithms.h"
-#include "cmCommand.h"
 #include "cmCommandArgumentParserHelper.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
@@ -388,12 +387,8 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
   }
 
   // Lookup the command prototype.
-  if (cmCommand* proto =
+  if (cmState::Command command =
         this->GetState()->GetCommandByExactName(lff.Name.Lower)) {
-    // Clone the prototype.
-    std::unique_ptr<cmCommand> pcmd(proto->Clone());
-    pcmd->SetMakefile(this);
-
     // Decide whether to invoke the command.
     if (!cmSystemTools::GetFatalErrorOccured()) {
       // if trace is enabled, print out invoke information
@@ -401,13 +396,13 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
         this->PrintCommandTrace(lff);
       }
       // Try invoking the command.
-      bool invokeSucceeded = pcmd->InvokeInitialPass(lff.Arguments, status);
+      bool invokeSucceeded = command(lff.Arguments, status);
       bool hadNestedError = status.GetNestedError();
       if (!invokeSucceeded || hadNestedError) {
         if (!hadNestedError) {
           // The command invocation requested that we report an error.
           std::string const error =
-            std::string(lff.Name.Original) + " " + pcmd->GetError();
+            std::string(lff.Name.Original) + " " + status.GetError();
           this->IssueMessage(MessageType::FATAL_ERROR, error);
         }
         result = false;
@@ -657,7 +652,7 @@ void cmMakefile::ReadListFile(cmListFile const& listFile,
   // Run the parsed commands.
   const size_t numberFunctions = listFile.Functions.size();
   for (size_t i = 0; i < numberFunctions; ++i) {
-    cmExecutionStatus status;
+    cmExecutionStatus status(*this);
     this->ExecuteCommand(listFile.Functions[i], status);
     if (cmSystemTools::GetFatalErrorOccured()) {
       break;

+ 2 - 2
Source/cmReturnCommand.cxx

@@ -5,8 +5,8 @@
 #include "cmExecutionStatus.h"
 
 // cmReturnCommand
-bool cmReturnCommand::InitialPass(std::vector<std::string> const&,
-                                  cmExecutionStatus& status)
+bool cmReturnCommand(std::vector<std::string> const&,
+                     cmExecutionStatus& status)
 {
   status.SetReturnInvoked();
   return true;

+ 3 - 27
Source/cmReturnCommand.h

@@ -8,34 +8,10 @@
 #include <string>
 #include <vector>
 
-#include "cm_memory.hxx"
-
-#include "cmCommand.h"
-
 class cmExecutionStatus;
 
-/** \class cmReturnCommand
- * \brief Return from a directory or function
- *
- * cmReturnCommand returns from a directory or function
- */
-class cmReturnCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  std::unique_ptr<cmCommand> Clone() override
-  {
-    return cm::make_unique<cmReturnCommand>();
-  }
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const& args,
-                   cmExecutionStatus& status) override;
-};
+/// Return from a directory or function
+bool cmReturnCommand(std::vector<std::string> const& args,
+                     cmExecutionStatus& status);
 
 #endif

+ 47 - 31
Source/cmState.cxx

@@ -5,8 +5,8 @@
 #include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
+#include <stdlib.h>
 #include <string.h>
-#include <type_traits>
 #include <utility>
 
 #include "cm_memory.hxx"
@@ -16,12 +16,13 @@
 #include "cmCommand.h"
 #include "cmDefinitions.h"
 #include "cmDisallowedCommand.h"
+#include "cmExecutionStatus.h"
 #include "cmGlobVerificationManager.h"
 #include "cmListFileCache.h"
+#include "cmMakefile.h"
 #include "cmStatePrivate.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
-#include "cmUnexpectedCommand.h"
 #include "cmake.h"
 
 cmState::cmState()
@@ -420,12 +421,32 @@ void cmState::SetIsGeneratorMultiConfig(bool b)
 
 void cmState::AddBuiltinCommand(std::string const& name,
                                 std::unique_ptr<cmCommand> command)
+{
+  this->AddBuiltinCommand(name, cmLegacyCommandWrapper(std::move(command)));
+}
+
+void cmState::AddBuiltinCommand(std::string const& name, Command command)
 {
   assert(name == cmSystemTools::LowerCase(name));
   assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end());
-  this->BuiltinCommands.insert(
-    std::map<std::string, std::unique_ptr<cmCommand>>::value_type(
-      name, std::move(command)));
+  this->BuiltinCommands.emplace(name, std::move(command));
+}
+
+void cmState::AddBuiltinCommand(std::string const& name,
+                                BuiltinCommand command)
+{
+  this->AddBuiltinCommand(
+    name,
+    [command](const std::vector<cmListFileArgument>& args,
+              cmExecutionStatus& status) -> bool {
+      std::vector<std::string> expandedArguments;
+      if (!status.GetMakefile().ExpandArguments(args, expandedArguments)) {
+        // There was an error expanding arguments.  It was already
+        // reported, so we can skip this command without error.
+        return true;
+      }
+      return command(expandedArguments, status);
+    });
 }
 
 void cmState::AddDisallowedCommand(std::string const& name,
@@ -440,49 +461,46 @@ void cmState::AddDisallowedCommand(std::string const& name,
 
 void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
 {
-  this->AddBuiltinCommand(name,
-                          cm::make_unique<cmUnexpectedCommand>(name, error));
+  this->AddBuiltinCommand(
+    name,
+    [name, error](std::vector<cmListFileArgument> const&,
+                  cmExecutionStatus& status) -> bool {
+      const char* versionValue =
+        status.GetMakefile().GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
+      if (name == "endif" && (!versionValue || atof(versionValue) <= 1.4)) {
+        return true;
+      }
+      status.SetError(error);
+      return false;
+    });
 }
 
-void cmState::AddScriptedCommand(std::string const& name,
-                                 std::unique_ptr<cmCommand> command)
+void cmState::AddScriptedCommand(std::string const& name, Command command)
 {
   std::string sName = cmSystemTools::LowerCase(name);
 
   // if the command already exists, give a new name to the old command.
-  if (cmCommand* oldCmd = this->GetCommand(sName)) {
-    std::string const newName = "_" + sName;
-    auto pos = this->ScriptedCommands.find(newName);
-    if (pos != this->ScriptedCommands.end()) {
-      this->ScriptedCommands.erase(pos);
-    }
-    this->ScriptedCommands.insert(std::make_pair(newName, oldCmd->Clone()));
+  if (Command oldCmd = this->GetCommand(sName)) {
+    this->ScriptedCommands["_" + sName] = oldCmd;
   }
 
-  // if the command already exists, free the old one
-  auto pos = this->ScriptedCommands.find(sName);
-  if (pos != this->ScriptedCommands.end()) {
-    this->ScriptedCommands.erase(pos);
-  }
-  this->ScriptedCommands.insert(
-    std::map<std::string, std::unique_ptr<cmCommand>>::value_type(
-      sName, std::move(command)));
+  this->ScriptedCommands[sName] = std::move(command);
 }
 
-cmCommand* cmState::GetCommand(std::string const& name) const
+cmState::Command cmState::GetCommand(std::string const& name) const
 {
   return GetCommandByExactName(cmSystemTools::LowerCase(name));
 }
 
-cmCommand* cmState::GetCommandByExactName(std::string const& name) const
+cmState::Command cmState::GetCommandByExactName(std::string const& name) const
 {
   auto pos = this->ScriptedCommands.find(name);
   if (pos != this->ScriptedCommands.end()) {
-    return pos->second.get();
+    return pos->second;
   }
   pos = this->BuiltinCommands.find(name);
   if (pos != this->BuiltinCommands.end()) {
-    return pos->second.get();
+    return pos->second;
   }
   return nullptr;
 }
@@ -507,9 +525,7 @@ std::vector<std::string> cmState::GetCommandNames() const
 void cmState::RemoveBuiltinCommand(std::string const& name)
 {
   assert(name == cmSystemTools::LowerCase(name));
-  auto i = this->BuiltinCommands.find(name);
-  assert(i != this->BuiltinCommands.end());
-  this->BuiltinCommands.erase(i);
+  this->BuiltinCommands.erase(name);
 }
 
 void cmState::RemoveUserDefinedCommands()

+ 14 - 6
Source/cmState.h

@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <functional>
 #include <map>
 #include <memory>
 #include <set>
@@ -27,6 +28,7 @@ class cmGlobVerificationManager;
 class cmPropertyDefinition;
 class cmStateSnapshot;
 class cmMessenger;
+class cmExecutionStatus;
 
 class cmState
 {
@@ -141,19 +143,25 @@ public:
   bool GetIsGeneratorMultiConfig() const;
   void SetIsGeneratorMultiConfig(bool b);
 
+  using Command = std::function<bool(std::vector<cmListFileArgument> const&,
+                                     cmExecutionStatus&)>;
+  using BuiltinCommand = bool (*)(std::vector<std::string> const&,
+                                  cmExecutionStatus&);
+
   // Returns a command from its name, case insensitive, or nullptr
-  cmCommand* GetCommand(std::string const& name) const;
+  Command GetCommand(std::string const& name) const;
   // Returns a command from its name, or nullptr
-  cmCommand* GetCommandByExactName(std::string const& name) const;
+  Command GetCommandByExactName(std::string const& name) const;
 
   void AddBuiltinCommand(std::string const& name,
                          std::unique_ptr<cmCommand> command);
+  void AddBuiltinCommand(std::string const& name, Command command);
+  void AddBuiltinCommand(std::string const& name, BuiltinCommand command);
   void AddDisallowedCommand(std::string const& name,
                             std::unique_ptr<cmCommand> command,
                             cmPolicies::PolicyID policy, const char* message);
   void AddUnexpectedCommand(std::string const& name, const char* error);
-  void AddScriptedCommand(std::string const& name,
-                          std::unique_ptr<cmCommand> command);
+  void AddScriptedCommand(std::string const& name, Command command);
   void RemoveBuiltinCommand(std::string const& name);
   void RemoveUserDefinedCommands();
   std::vector<std::string> GetCommandNames() const;
@@ -212,8 +220,8 @@ private:
 
   std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions;
   std::vector<std::string> EnabledLanguages;
-  std::map<std::string, std::unique_ptr<cmCommand>> BuiltinCommands;
-  std::map<std::string, std::unique_ptr<cmCommand>> ScriptedCommands;
+  std::map<std::string, Command> BuiltinCommands;
+  std::map<std::string, Command> ScriptedCommands;
   cmPropertyMap GlobalProperties;
   std::unique_ptr<cmCacheManager> CacheManager;
   std::unique_ptr<cmGlobVerificationManager> GlobVerificationManager;

+ 0 - 22
Source/cmUnexpectedCommand.cxx

@@ -1,22 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmUnexpectedCommand.h"
-
-#include <stdlib.h>
-
-#include "cmMakefile.h"
-
-class cmExecutionStatus;
-
-bool cmUnexpectedCommand::InitialPass(std::vector<std::string> const&,
-                                      cmExecutionStatus&)
-{
-  const char* versionValue =
-    this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
-  if (this->Name == "endif" && (!versionValue || atof(versionValue) <= 1.4)) {
-    return true;
-  }
-
-  this->SetError(this->Error);
-  return false;
-}

+ 0 - 40
Source/cmUnexpectedCommand.h

@@ -1,40 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#ifndef cmUnexpectedCommand_h
-#define cmUnexpectedCommand_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "cm_memory.hxx"
-
-#include "cmCommand.h"
-
-class cmExecutionStatus;
-
-class cmUnexpectedCommand : public cmCommand
-{
-public:
-  cmUnexpectedCommand(std::string name, const char* error)
-    : Name(std::move(name))
-    , Error(error)
-  {
-  }
-
-  std::unique_ptr<cmCommand> Clone() override
-  {
-    return cm::make_unique<cmUnexpectedCommand>(this->Name, this->Error);
-  }
-
-  bool InitialPass(std::vector<std::string> const& args,
-                   cmExecutionStatus& status) override;
-
-private:
-  std::string Name;
-  const char* Error;
-};
-
-#endif

+ 1 - 1
Source/cmVariableWatchCommand.cxx

@@ -55,7 +55,7 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable,
     newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999);
     newLFF.Name = data->Command;
     newLFF.Line = 9999;
-    cmExecutionStatus status;
+    cmExecutionStatus status(*makefile);
     if (!makefile->ExecuteCommand(newLFF, status)) {
       std::ostringstream error;
       error << "Error in cmake code at\nUnknown:0:\n"

+ 8 - 6
Source/cmWhileCommand.cxx

@@ -11,6 +11,7 @@
 #include "cmMessageType.h"
 #include "cmSystemTools.h"
 
+#include <string>
 #include <utility>
 
 cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf)
@@ -82,7 +83,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
 
         // Invoke all the functions that were collected in the block.
         for (cmListFileFunction const& fn : this->Functions) {
-          cmExecutionStatus status;
+          cmExecutionStatus status(mf);
           mf.ExecuteCommand(fn, status);
           if (status.GetReturnInvoked()) {
             inStatus.SetReturnInvoked();
@@ -129,19 +130,20 @@ bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
   return false;
 }
 
-bool cmWhileCommand::InvokeInitialPass(
-  const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
+bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
+                    cmExecutionStatus& status)
 {
   if (args.empty()) {
-    this->SetError("called with incorrect number of arguments");
+    status.SetError("called with incorrect number of arguments");
     return false;
   }
 
   // create a function blocker
   {
-    auto fb = cm::make_unique<cmWhileFunctionBlocker>(this->Makefile);
+    cmMakefile& makefile = status.GetMakefile();
+    auto fb = cm::make_unique<cmWhileFunctionBlocker>(&makefile);
     fb->Args = args;
-    this->Makefile->AddFunctionBlocker(std::move(fb));
+    makefile.AddFunctionBlocker(std::move(fb));
   }
   return true;
 }

+ 2 - 32
Source/cmWhileCommand.h

@@ -5,12 +5,8 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <string>
 #include <vector>
 
-#include "cm_memory.hxx"
-
-#include "cmCommand.h"
 #include "cmFunctionBlocker.h"
 #include "cmListFileCache.h"
 
@@ -35,33 +31,7 @@ private:
 };
 
 /// \brief Starts a while loop
-class cmWhileCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  std::unique_ptr<cmCommand> Clone() override
-  {
-    return cm::make_unique<cmWhileCommand>();
-  }
-
-  /**
-   * This overrides the default InvokeInitialPass implementation.
-   * It records the arguments before expansion.
-   */
-  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                         cmExecutionStatus&) override;
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override
-  {
-    return false;
-  }
-};
+bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
+                    cmExecutionStatus& status);
 
 #endif

+ 0 - 1
bootstrap

@@ -440,7 +440,6 @@ CMAKE_CXX_SOURCES="\
   cmTimestamp \
   cmTryCompileCommand \
   cmTryRunCommand \
-  cmUnexpectedCommand \
   cmUnsetCommand \
   cmUVHandlePtr \
   cmUVProcessChain \