Sfoglia il codice sorgente

cmake_parse_arguments: consider duplicate keyword as warning

The behaviour of double specified keywords is rather undefined or at
least not clearly documented. This change introduces a strict check and
emits a warning in case a keyword has been specified more than once.
Matthias Maennich 10 anni fa
parent
commit
ab8a280857

+ 7 - 0
Help/command/cmake_parse_arguments.rst

@@ -25,6 +25,13 @@ The ``<multi_value_keywords>`` argument contains all keywords for this
 macro which can be followed by more than one value, like e.g. the
 ``TARGETS`` or ``FILES`` keywords of the :command:`install` command.
 
+.. note::
+
+   All keywords shall be unique. I.e. every keyword shall only be specified
+   once in either ``<options>``, ``<one_value_keywords>`` or
+   ``<multi_value_keywords>``. A warning will be emitted if uniqueness is
+   violated.
+
 When done, ``cmake_parse_arguments`` will have defined for each of the
 keywords listed in ``<options>``, ``<one_value_keywords>`` and
 ``<multi_value_keywords>`` a variable composed of the given ``<prefix>``

+ 16 - 0
Source/cmParseArgumentsCommand.cxx

@@ -43,6 +43,10 @@ bool cmParseArgumentsCommand
   // anything else is put into a vector of unparsed strings
   std::vector<std::string> unparsed;
 
+  // remember already defined keywords
+  std::set<std::string> used_keywords;
+  const std::string dup_warning = "keyword defined more than once: ";
+
   // the second argument is a (cmake) list of options without argument
   std::vector<std::string> list;
   cmSystemTools::ExpandListArgument(*argIter++, list);
@@ -50,6 +54,10 @@ bool cmParseArgumentsCommand
                                                 end   = list.end();
                                                 iter != end; ++iter)
     {
+    if (!used_keywords.insert(*iter).second)
+      {
+      this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
+      }
     options[*iter]; // default initialize
     }
 
@@ -60,6 +68,10 @@ bool cmParseArgumentsCommand
                                                 end   = list.end();
                                                 iter != end; ++iter)
     {
+    if (!used_keywords.insert(*iter).second)
+      {
+      this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
+      }
     single[*iter]; // default initialize
     }
 
@@ -70,6 +82,10 @@ bool cmParseArgumentsCommand
                                                 end   = list.end();
                                                 iter != end; ++iter)
     {
+    if (!used_keywords.insert(*iter).second)
+      {
+      this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
+      }
     multi[*iter]; // default initialize
     }
 

+ 33 - 3
Tests/RunCMake/cmake_parse_arguments/Errors-stderr.txt

@@ -1,14 +1,44 @@
-CMake Error at Errors\.cmake:1 \(cmake_parse_arguments\):
+CMake Error at Errors\.cmake:2 \(cmake_parse_arguments\):
   cmake_parse_arguments must be called with at least 4 arguments\.
 Call Stack \(most recent call first\):
   CMakeLists\.txt:3 \(include\)
 +
-CMake Error at Errors\.cmake:2 \(cmake_parse_arguments\):
+CMake Error at Errors\.cmake:3 \(cmake_parse_arguments\):
   cmake_parse_arguments must be called with at least 4 arguments\.
 Call Stack \(most recent call first\):
   CMakeLists\.txt:3 \(include\)
 +
-CMake Error at Errors\.cmake:3 \(cmake_parse_arguments\):
+CMake Error at Errors\.cmake:4 \(cmake_parse_arguments\):
   cmake_parse_arguments must be called with at least 4 arguments\.
 Call Stack \(most recent call first\):
   CMakeLists\.txt:3 \(include\)
++
+CMake Warning at Errors\.cmake:8 \(cmake_parse_arguments\):
+  keyword defined more than once: OPT
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)
++
+CMake Warning at Errors\.cmake:9 \(cmake_parse_arguments\):
+  keyword defined more than once: OPT
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)
++
+CMake Warning at Errors\.cmake:10 \(cmake_parse_arguments\):
+  keyword defined more than once: OPT
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)
++
+CMake Warning at Errors\.cmake:12 \(cmake_parse_arguments\):
+  keyword defined more than once: OPT
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)
++
+CMake Warning at Errors\.cmake:13 \(cmake_parse_arguments\):
+  keyword defined more than once: OPT
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)
++
+CMake Warning at Errors\.cmake:14 \(cmake_parse_arguments\):
+  keyword defined more than once: OPT
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)

+ 10 - 0
Tests/RunCMake/cmake_parse_arguments/Errors.cmake

@@ -1,4 +1,14 @@
+# wrong argument count
 cmake_parse_arguments()
 cmake_parse_arguments(prefix OPT)
 cmake_parse_arguments(prefix OPT SINGLE)
 cmake_parse_arguments(prefix OPT SINGLE MULTI) # not an error
+
+# duplicate keywords
+cmake_parse_arguments(prefix "OPT;OPT" "" "")
+cmake_parse_arguments(prefix "" "OPT;OPT" "")
+cmake_parse_arguments(prefix "" "" "OPT;OPT")
+
+cmake_parse_arguments(prefix "OPT" "OPT" "")
+cmake_parse_arguments(prefix "" "OPT" "OPT")
+cmake_parse_arguments(prefix "OPT" "" "OPT")