From c017098d4d06ba114085ba7de47b99fc0b71e8d0 Mon Sep 17 00:00:00 2001
From: Kyle Edwards <kyle.edwards@kitware.com>
Date: Wed, 16 Jun 2021 10:39:39 -0400
Subject: [PATCH] CMake: Allow override of unexpected non-flow-control commands

Fixes: #22310
---
 Source/cmCommands.cxx                            | 14 +++++++-------
 Source/cmState.cxx                               |  9 ++++++++-
 Source/cmState.h                                 |  2 ++
 Tests/RunCMake/Syntax/OverrideProject-result.txt |  1 +
 Tests/RunCMake/Syntax/OverrideProject-stderr.txt |  3 +++
 Tests/RunCMake/Syntax/RunCMakeTest.cmake         |  1 +
 6 files changed, 22 insertions(+), 8 deletions(-)
 create mode 100644 Tests/RunCMake/Syntax/OverrideProject-result.txt
 create mode 100644 Tests/RunCMake/Syntax/OverrideProject-stderr.txt

diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 9e5b78351d1..a241a3a6430 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -164,36 +164,36 @@ void GetScriptingCommands(cmState* state)
   state->AddBuiltinCommand("string", cmStringCommand);
   state->AddBuiltinCommand("unset", cmUnsetCommand);
 
-  state->AddUnexpectedCommand(
+  state->AddUnexpectedFlowControlCommand(
     "else",
     "An ELSE command was found outside of a proper "
     "IF ENDIF structure. Or its arguments did not match "
     "the opening IF command.");
-  state->AddUnexpectedCommand(
+  state->AddUnexpectedFlowControlCommand(
     "elseif",
     "An ELSEIF command was found outside of a proper "
     "IF ENDIF structure.");
-  state->AddUnexpectedCommand(
+  state->AddUnexpectedFlowControlCommand(
     "endforeach",
     "An ENDFOREACH command was found outside of a proper "
     "FOREACH ENDFOREACH structure. Or its arguments did "
     "not match the opening FOREACH command.");
-  state->AddUnexpectedCommand(
+  state->AddUnexpectedFlowControlCommand(
     "endfunction",
     "An ENDFUNCTION command was found outside of a proper "
     "FUNCTION ENDFUNCTION structure. Or its arguments did not "
     "match the opening FUNCTION command.");
-  state->AddUnexpectedCommand(
+  state->AddUnexpectedFlowControlCommand(
     "endif",
     "An ENDIF command was found outside of a proper "
     "IF ENDIF structure. Or its arguments did not match "
     "the opening IF command.");
-  state->AddUnexpectedCommand(
+  state->AddUnexpectedFlowControlCommand(
     "endmacro",
     "An ENDMACRO command was found outside of a proper "
     "MACRO ENDMACRO structure. Or its arguments did not "
     "match the opening MACRO command.");
-  state->AddUnexpectedCommand(
+  state->AddUnexpectedFlowControlCommand(
     "endwhile",
     "An ENDWHILE command was found outside of a proper "
     "WHILE ENDWHILE structure. Or its arguments did not "
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index d97762bb6c4..929b0fba96a 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -480,7 +480,7 @@ void cmState::AddDisallowedCommand(std::string const& name,
 
 void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
 {
-  this->AddFlowControlCommand(
+  this->AddBuiltinCommand(
     name,
     [name, error](std::vector<cmListFileArgument> const&,
                   cmExecutionStatus& status) -> bool {
@@ -495,6 +495,13 @@ void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
     });
 }
 
+void cmState::AddUnexpectedFlowControlCommand(std::string const& name,
+                                              const char* error)
+{
+  this->FlowControlCommands.insert(name);
+  this->AddUnexpectedCommand(name, error);
+}
+
 bool cmState::AddScriptedCommand(std::string const& name, BT<Command> command,
                                  cmMakefile& mf)
 {
diff --git a/Source/cmState.h b/Source/cmState.h
index 4e411560a17..9951b9acfee 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -166,6 +166,8 @@ public:
   void AddDisallowedCommand(std::string const& name, BuiltinCommand command,
                             cmPolicies::PolicyID policy, const char* message);
   void AddUnexpectedCommand(std::string const& name, const char* error);
+  void AddUnexpectedFlowControlCommand(std::string const& name,
+                                       const char* error);
   bool AddScriptedCommand(std::string const& name, BT<Command> command,
                           cmMakefile& mf);
   void RemoveBuiltinCommand(std::string const& name);
diff --git a/Tests/RunCMake/Syntax/OverrideProject-result.txt b/Tests/RunCMake/Syntax/OverrideProject-result.txt
new file mode 100644
index 00000000000..d00491fd7e5
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideProject-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideProject-stderr.txt b/Tests/RunCMake/Syntax/OverrideProject-stderr.txt
new file mode 100644
index 00000000000..862d5c87308
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideProject-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error at [^
+]*/Tests/RunCMake/Syntax/Override\.cmake:[0-9]+ \(message\):
+  This shouldn't happen$
diff --git a/Tests/RunCMake/Syntax/RunCMakeTest.cmake b/Tests/RunCMake/Syntax/RunCMakeTest.cmake
index 4d246577b20..f0c287cdb91 100644
--- a/Tests/RunCMake/Syntax/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Syntax/RunCMakeTest.cmake
@@ -150,3 +150,4 @@ run_override(If)
 run_override(Macro)
 run_override(Return)
 run_override(While)
+run_override(Project)
-- 
GitLab