Browse Source

Merge topic 'foreach-assertion'

ac8fe36aba Help: Improve clarity of foreach behavior
37e27f71bc foreach: Explicitly skip replay without iterations

Acked-by: Kitware Robot <[email protected]>
Merge-request: !11081
Brad King 3 months ago
parent
commit
ced6ca50f1

+ 12 - 6
Help/command/foreach.rst

@@ -58,7 +58,8 @@ command iterates over each item in each given list.
 The ``<items>`` following the ``ITEMS`` keyword are processed
 as in the first variant of the ``foreach`` command.
 The forms ``LISTS A`` and ``ITEMS ${A}`` are
-equivalent.
+equivalent. If no ``<lists>`` or ``<items>`` are given, the body
+of the loop will never be executed (i.e., it is processed as empty).
 
 The following example shows how the ``LISTS`` option is
 processed:
@@ -97,13 +98,18 @@ separated list of list-valued variables. The ``foreach``
 command iterates over each list simultaneously setting the
 iteration variables as follows:
 
-- if the only ``loop_var`` given, then it sets a series of
+- if a single ``loop_var`` is given, then it sets a series of
   ``loop_var_N`` variables to the current item from the
   corresponding list;
-- if multiple variable names passed, their count should match
-  the lists variables count;
-- if any of the lists are shorter, the corresponding iteration
-  variable is not defined for the current iteration.
+- if multiple variable names are passed, it sets each variable to the
+  current item from the corresponding list. The number of iteration
+  variables must match the number of list variables.
+
+If no ``<lists>`` are given, the body of the loop will never be executed
+(i.e., it is processed as empty).
+
+The following example shows how the ``ZIP_LISTS`` option is
+processed:
 
 .. noqa: spellcheck off
 

+ 3 - 0
Source/cmForEachCommand.cxx

@@ -100,6 +100,9 @@ bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
 bool cmForEachFunctionBlocker::Replay(
   std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus)
 {
+  if (this->Args.size() == this->IterationVarsCount) {
+    return true;
+  }
   return this->ZipLists ? this->ReplayZipLists(functions, inStatus)
                         : this->ReplayItems(functions, inStatus);
 }

+ 1 - 0
Tests/RunCMake/foreach/RunCMakeTest.cmake

@@ -22,3 +22,4 @@ run_cmake(foreach-RANGE-invalid-test)
 run_cmake(foreach-RANGE-out-of-range-test)
 run_cmake(foreach-var-scope-CMP0124-OLD)
 run_cmake(foreach-var-scope-CMP0124-NEW)
+run_cmake(TrailingIn)

+ 1 - 0
Tests/RunCMake/foreach/TrailingIn-result.txt

@@ -0,0 +1 @@
+0

+ 5 - 0
Tests/RunCMake/foreach/TrailingIn.cmake

@@ -0,0 +1,5 @@
+foreach(v IN)
+endforeach()
+
+foreach(v1 v2 IN)
+endforeach()