From ab8a280857da5cf8545bd2a6f69b7378f53449a5 Mon Sep 17 00:00:00 2001 From: Matthias Maennich Date: Sat, 5 Dec 2015 19:02:19 +0100 Subject: [PATCH] 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. --- Help/command/cmake_parse_arguments.rst | 7 ++++ Source/cmParseArgumentsCommand.cxx | 16 ++++++++ .../cmake_parse_arguments/Errors-stderr.txt | 40 ++++++++++++++++--- .../cmake_parse_arguments/Errors.cmake | 10 +++++ 4 files changed, 68 insertions(+), 5 deletions(-) diff --git a/Help/command/cmake_parse_arguments.rst b/Help/command/cmake_parse_arguments.rst index 7638b6102..6206611d2 100644 --- a/Help/command/cmake_parse_arguments.rst +++ b/Help/command/cmake_parse_arguments.rst @@ -25,6 +25,13 @@ The ```` 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 ````, ```` or + ````. A warning will be emitted if uniqueness is + violated. + When done, ``cmake_parse_arguments`` will have defined for each of the keywords listed in ````, ```` and ```` a variable composed of the given ```` diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index ce7a7b3cd..a86196515 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -43,6 +43,10 @@ bool cmParseArgumentsCommand // anything else is put into a vector of unparsed strings std::vector unparsed; + // remember already defined keywords + std::set 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 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 } diff --git a/Tests/RunCMake/cmake_parse_arguments/Errors-stderr.txt b/Tests/RunCMake/cmake_parse_arguments/Errors-stderr.txt index 5394eaf1b..f2ba9b84e 100644 --- a/Tests/RunCMake/cmake_parse_arguments/Errors-stderr.txt +++ b/Tests/RunCMake/cmake_parse_arguments/Errors-stderr.txt @@ -1,8 +1,3 @@ -CMake Error at Errors\.cmake:1 \(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_parse_arguments must be called with at least 4 arguments\. Call Stack \(most recent call first\): @@ -12,3 +7,38 @@ 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: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\) diff --git a/Tests/RunCMake/cmake_parse_arguments/Errors.cmake b/Tests/RunCMake/cmake_parse_arguments/Errors.cmake index 98e22e94d..6a380810d 100644 --- a/Tests/RunCMake/cmake_parse_arguments/Errors.cmake +++ b/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")