Browse Source

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 years ago
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
 macro which can be followed by more than one value, like e.g. the
 ``TARGETS`` or ``FILES`` keywords of the :command:`install` command.
 ``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
 When done, ``cmake_parse_arguments`` will have defined for each of the
 keywords listed in ``<options>``, ``<one_value_keywords>`` and
 keywords listed in ``<options>``, ``<one_value_keywords>`` and
 ``<multi_value_keywords>`` a variable composed of the given ``<prefix>``
 ``<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
   // anything else is put into a vector of unparsed strings
   std::vector<std::string> unparsed;
   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
   // the second argument is a (cmake) list of options without argument
   std::vector<std::string> list;
   std::vector<std::string> list;
   cmSystemTools::ExpandListArgument(*argIter++, list);
   cmSystemTools::ExpandListArgument(*argIter++, list);
@@ -50,6 +54,10 @@ bool cmParseArgumentsCommand
                                                 end   = list.end();
                                                 end   = list.end();
                                                 iter != end; ++iter)
                                                 iter != end; ++iter)
     {
     {
+    if (!used_keywords.insert(*iter).second)
+      {
+      this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
+      }
     options[*iter]; // default initialize
     options[*iter]; // default initialize
     }
     }
 
 
@@ -60,6 +68,10 @@ bool cmParseArgumentsCommand
                                                 end   = list.end();
                                                 end   = list.end();
                                                 iter != end; ++iter)
                                                 iter != end; ++iter)
     {
     {
+    if (!used_keywords.insert(*iter).second)
+      {
+      this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
+      }
     single[*iter]; // default initialize
     single[*iter]; // default initialize
     }
     }
 
 
@@ -70,6 +82,10 @@ bool cmParseArgumentsCommand
                                                 end   = list.end();
                                                 end   = list.end();
                                                 iter != end; ++iter)
                                                 iter != end; ++iter)
     {
     {
+    if (!used_keywords.insert(*iter).second)
+      {
+      this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
+      }
     multi[*iter]; // default initialize
     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\.
   cmake_parse_arguments must be called with at least 4 arguments\.
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists\.txt:3 \(include\)
   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\.
   cmake_parse_arguments must be called with at least 4 arguments\.
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists\.txt:3 \(include\)
   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\.
   cmake_parse_arguments must be called with at least 4 arguments\.
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists\.txt:3 \(include\)
   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()
 cmake_parse_arguments(prefix OPT)
 cmake_parse_arguments(prefix OPT)
 cmake_parse_arguments(prefix OPT SINGLE)
 cmake_parse_arguments(prefix OPT SINGLE)
 cmake_parse_arguments(prefix OPT SINGLE MULTI) # not an error
 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")