From c781998273f858c81b37cb32c4d02b15ce090239 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Sun, 26 Jun 2022 14:53:01 -0400 Subject: [PATCH] chore: clang tidy updates (#742) --- .ci/azure-build.yml | 8 +++++++- .ci/make_and_test.sh | 2 +- .clang-tidy | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- .github/CONTRIBUTING.md | 7 ++++--- .github/workflows/tests.yml | 16 ++++++++++++++++ CMakeLists.txt | 33 ++++++++++++++++----------------- azure-pipelines.yml | 20 -------------------- examples/CMakeLists.txt | 3 --- examples/custom_parse.cpp | 2 +- examples/formatter.cpp | 4 ++-- examples/groups.cpp | 2 +- examples/inter_argument_order.cpp | 6 +++--- examples/modhelp.cpp | 2 +- examples/option_groups.cpp | 4 ++-- examples/positional_arity.cpp | 4 ++-- examples/prefix_command.cpp | 2 +- examples/ranges.cpp | 2 +- examples/retired.cpp | 4 ++-- examples/shapes.cpp | 6 +++--- examples/subcom_in_files/subcommand_a.cpp | 2 +- examples/subcom_partitioned.cpp | 2 +- examples/subcommands.cpp | 2 +- examples/testEXE.cpp | 2 +- include/CLI/App.hpp | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------- include/CLI/Config.hpp | 14 +++++++------- include/CLI/ConfigFwd.hpp | 10 +++++----- include/CLI/Error.hpp | 32 +++++++++++++++----------------- include/CLI/Formatter.hpp | 2 +- include/CLI/FormatterFwd.hpp | 10 +++++----- include/CLI/Macros.hpp | 8 ++++++++ include/CLI/Option.hpp | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------------- include/CLI/Split.hpp | 9 ++++----- include/CLI/StringTools.hpp | 2 +- include/CLI/Timer.hpp | 17 +++++++++-------- include/CLI/TypeTools.hpp | 41 +++++++++++++++++++++-------------------- include/CLI/Validators.hpp | 59 +++++++++++++++++++++++++++++++---------------------------- tests/AppTest.cpp | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------- tests/ComplexTypeTest.cpp | 8 ++++---- tests/ConfigFileTest.cpp | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------- tests/CreationTest.cpp | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------- tests/HelpTest.cpp | 62 +++++++++++++++++++++++++++++++------------------------------- tests/HelpersTest.cpp | 52 +++++++++++++++++++++++++++------------------------- tests/NewParseTest.cpp | 27 +++++++++++++++------------ tests/OptionGroupTest.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++------------------------------------------ tests/OptionTypeTest.cpp | 43 ++++++++++++++++++++++++------------------- tests/SetTest.cpp | 73 +++++++++++++++++++++++++++++++++++++------------------------------------ tests/StringParseTest.cpp | 6 +++--- tests/SubcommandTest.cpp | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------- tests/TransformTest.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------ tests/app_helper.hpp | 4 ++-- 50 files changed, 970 insertions(+), 879 deletions(-) diff --git a/.ci/azure-build.yml b/.ci/azure-build.yml index 22f3306..fbe674c 100644 --- a/.ci/azure-build.yml +++ b/.ci/azure-build.yml @@ -8,6 +8,12 @@ steps: -DCMAKE_BUILD_TYPE=$(cli11.build_type) $(cli11.options) displayName: "Configure" + - script: cmake --build . -- -j2 --keep-going + displayName: "Build Unix" + workingDirectory: build + condition: ne( variables['Agent.OS'], 'Windows_NT' ) + - script: cmake --build . - displayName: "Build" + displayName: "Build Windows" workingDirectory: build + condition: eq( variables['Agent.OS'], 'Windows_NT' ) diff --git a/.ci/make_and_test.sh b/.ci/make_and_test.sh index 07df22e..a52c946 100755 --- a/.ci/make_and_test.sh +++ b/.ci/make_and_test.sh @@ -9,7 +9,7 @@ set -evx mkdir -p build cd build cmake .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE=ON -DCMAKE_CXX_STANDARD="$STD" -DCLI11_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER_LAUNCHER=ccache $@ -cmake --build . -- -j2 +cmake --build . -- -j2 --keep-going set +evx echo -en "travis_fold:end:script.build\\r" diff --git a/.clang-tidy b/.clang-tidy index b135afe..47a367d 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,17 +1,80 @@ # Checks that will be implemented in future PRs: # performance-unnecessary-value-param, hints to ~110 issues. Be careful with implementing the suggested changes of this one, as auto-fixes may break the code +# bugprone-forwarding-reference-overload probably should be enabled and fixed. +# clang-diagnostic-float-equal can be fixed by using _a from Catch::literals +# bugprone-exception-escape due to main being a bit simple in examples +# modernize-avoid-c-arrays trips up in TEMPLATE_TEST_CASE catch macro +# modernize-return-braced-init-list triggers on lambdas ? +# modernize-make-unique requires C++14 -FormatStyle: file - -Checks: > - -*, google-*, -google-runtime-references, llvm-include-order, - llvm-namespace-comment, misc-throw-by-value-catch-by-reference, modernize*, - -modernize-use-trailing-return-type, readability-container-size-empty, - -WarningsAsErrors: "*" - -HeaderFilterRegex: ".*hpp" +Checks: | + *bugprone*, + -bugprone-easily-swappable-parameters, + -bugprone-forwarding-reference-overload, + -bugprone-exception-escape, + clang-analyzer-optin.cplusplus.VirtualCall, + clang-analyzer-optin.performance.Padding, + -clang-diagnostic-float-equal, + cppcoreguidelines-init-variables, + cppcoreguidelines-prefer-member-initializer, + cppcoreguidelines-pro-type-static-cast-downcast, + cppcoreguidelines-slicing, + google-*, + -google-runtime-references, + llvm-include-order, + llvm-namespace-comment, + misc-definitions-in-headers, + misc-misplaced-const, + misc-non-copyable-objects, + misc-static-assert, + misc-throw-by-value-catch-by-reference, + misc-throw-by-value-catch-by-reference, + misc-uniqueptr-reset-release, + misc-unused-parameters, + modernize*, + -modernize-use-trailing-return-type, + -modernize-concat-nested-namespaces, + -modernize-return-braced-init-list, + -modernize-make-unique, + *performance*, + -performance-unnecessary-value-param, + -performance-inefficient-string-concatenation, + readability-avoid-const-params-in-decls, + readability-const-return-type, + readability-container-size-empty, + readability-delete-null-pointer, + readability-else-after-return, + readability-implicit-bool-conversion, + readability-inconsistent-declaration-parameter-name, + readability-make-member-function-const, + readability-misplaced-array-index, + readability-non-const-parameter, + readability-qualified-auto, + readability-redundant-function-ptr-dereference, + readability-redundant-smartptr-get, + readability-redundant-string-cstr, + readability-simplify-subscript-expr, + readability-static-accessed-through-instance, + readability-static-definition-in-anonymous-namespace, + readability-string-compare, + readability-suspicious-call-argument, + readability-uniqueptr-delete-release, CheckOptions: - key: google-readability-braces-around-statements.ShortStatementLines value: "3" + - key: performance-for-range-copy.WarnOnAllAutoCopies + value: true + - key: performance-inefficient-string-concatenation.StrictMode + value: true + - key: performance-unnecessary-value-param.AllowedTypes + value: "exception_ptr$;" + - key: readability-implicit-bool-conversion.AllowPointerConditions + value: true + - key: modernize-use-nodiscard.ReplacementString + value: "CLI11_NODISCARD" + +HeaderFilterRegex: "CLI.*hpp" + +FormatStyle: file +# WarningsAsErrors: "*" diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 6e7a1d8..7d37634 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -26,9 +26,10 @@ complexity of CLI11 needlessly. - Formatting should be done with pre-commit, otherwise the format check will not pass. However, it is trivial to apply this to your PR, so don't worry about this check. If you do want to run it, see below. -- Everything must pass clang-tidy as well, run with `-DCLI11_CLANG_TIDY=ON` (if - you set `-DCLI11_CLANG_TIDY_OPTIONS="-fix"`, make sure you use a single - threaded build process, or just build one example target). +- Everything must pass clang-tidy as well, run with + `-DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy)"` (if you set + `"$(which clang-tidy) -fix"`, make sure you use a single threaded build + process, or just build one example target). - Your changes must also conform to most of the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) rules checked by [cpplint](https://github.com/cpplint/cpplint). For unused diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 189e8df..efb15d2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,6 +7,22 @@ on: pull_request: jobs: + clang-tidy: + name: Clang-Tidy + runs-on: ubuntu-latest + container: silkeh/clang:14 + steps: + - uses: actions/checkout@v3 + + - name: Configure + run: > + cmake -S . -B build -DCMAKE_CXX_STANDARD=17 + -DCMAKE_CXX_CLANG_TIDY="$(which + clang-tidy);--use-color;--warnings-as-errors=*" + + - name: Build + run: cmake --build build -j4 -- --keep-going + cuda-build: name: CUDA build only runs-on: ubuntu-latest diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f4313f..c67031c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,13 +105,6 @@ cmake_dependent_option( CLI11_CUDA_TESTS "Build the tests with NVCC to check for warnings there - requires CMake 3.9+" OFF "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF) -cmake_dependent_option( - CLI11_CLANG_TIDY "Look for and use Clang-Tidy" OFF - "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME;NOT CMAKE_VERSION VERSION_LESS 3.6" OFF) -set(CLI11_CLANG_TIDY_OPTIONS - "" - CACHE STRING "Clang tidy options, such as -fix, semicolon separated") - if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 11) endif() @@ -134,6 +127,22 @@ add_library(CLI11_warnings INTERFACE) set(unix-warnings -Wall -Wextra -pedantic -Wshadow -Wsign-conversion -Wswitch-enum) +# Clang warnings +# -Wfloat-equal could be added with Catch::literals and _a usage +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + list( + APPEND + unix-warnings + -Wcast-align + -Wimplicit-atomic-properties + -Wmissing-declarations + -Woverlength-strings + -Wshadow + -Wstrict-selector-match + -Wundeclared-selector) + # -Wunreachable-code Doesn't work on Clang 3.4 +endif() + # Buggy in GCC 4.8 if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) list(APPEND unix-warnings -Weffc++) @@ -191,16 +200,6 @@ if(CLI11_CUDA_TESTS) set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --display_error_number") endif() -# Prepare Clang-Tidy -if(CLI11_CLANG_TIDY) - find_program( - CLANG_TIDY_EXE - NAMES "clang-tidy" - DOC "Path to clang-tidy executable" REQUIRED) - - set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" ${CLI11_CLANG_TIDY_OPTIONS}) -endif() - # This folder should be installed if(CLI11_INSTALL) install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 17944e8..11325d1 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -19,26 +19,6 @@ variables: CMAKE_BUILD_PARALLEL_LEVEL: 4 jobs: - - job: ClangTidy - variables: - CXX_FLAGS: > - -Werror -Wcast-align -Wfloat-equal -Wimplicit-atomic-properties - -Wmissing-declarations -Woverlength-strings -Wshadow - -Wstrict-selector-match -Wundeclared-selector -Wunreachable-code - -std=c++11 - cli11.options: -DCLI11_CLANG_TIDY=ON -DCLI11_CLANG_TIDY_OPTIONS="-fix" - cli11.std: 11 - cli11.single: OFF - CMAKE_BUILD_PARALLEL_LEVEL: 1 - pool: - vmImage: "ubuntu-latest" - container: silkeh/clang:8 - steps: - - template: .ci/azure-cmake.yml - - template: .ci/azure-build.yml - - script: git diff --exit-code --color - displayName: Check tidy - - job: CppLint pool: vmImage: "ubuntu-latest" diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 26747f0..e124df6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,9 +8,6 @@ function(add_cli_exe T) APPEND_STRING PROPERTY LINK_FLAGS -stdlib=libc++) endif() - if(CLI11_CLANG_TIDY) - set_property(TARGET ${T} PROPERTY CXX_CLANG_TIDY "${DO_CLANG_TIDY}") - endif() endfunction() if(CLI11_BUILD_EXAMPLES_JSON) diff --git a/examples/custom_parse.cpp b/examples/custom_parse.cpp index d24b994..793ddfa 100644 --- a/examples/custom_parse.cpp +++ b/examples/custom_parse.cpp @@ -22,7 +22,7 @@ template struct Values { using DoubleValues = Values; // the lexical cast operator should be in the same namespace as the type for ADL to work properly -bool lexical_cast(const std::string &input, Values &v) { +bool lexical_cast(const std::string &input, Values & /*v*/) { std::cout << "called correct lexical_cast function ! val: " << input << std::endl; return true; } diff --git a/examples/formatter.cpp b/examples/formatter.cpp index 8d3a974..09d6dce 100644 --- a/examples/formatter.cpp +++ b/examples/formatter.cpp @@ -24,9 +24,9 @@ int main(int argc, char **argv) { app.add_flag("--flag", "This is a flag"); - auto sub1 = app.add_subcommand("one", "Description One"); + auto *sub1 = app.add_subcommand("one", "Description One"); sub1->add_flag("--oneflag", "Some flag"); - auto sub2 = app.add_subcommand("two", "Description Two"); + auto *sub2 = app.add_subcommand("two", "Description Two"); sub2->add_flag("--twoflag", "Some other flag"); CLI11_PARSE(app, argc, argv); diff --git a/examples/groups.cpp b/examples/groups.cpp index e366dfe..2ebc1e8 100644 --- a/examples/groups.cpp +++ b/examples/groups.cpp @@ -10,7 +10,7 @@ #include int main(int argc, char **argv) { - CLI::AutoTimer("This is a timer"); + CLI::AutoTimer give_me_a_name("This is a timer"); CLI::App app("K3Pi goofit fitter"); diff --git a/examples/inter_argument_order.cpp b/examples/inter_argument_order.cpp index f90e755..8fe063e 100644 --- a/examples/inter_argument_order.cpp +++ b/examples/inter_argument_order.cpp @@ -14,10 +14,10 @@ int main(int argc, char **argv) { CLI::App app{"An app to practice mixing unlimited arguments, but still recover the original order."}; std::vector foos; - auto foo = app.add_option("--foo,-f", foos, "Some unlimited argument"); + auto *foo = app.add_option("--foo,-f", foos, "Some unlimited argument"); std::vector bars; - auto bar = app.add_option("--bar", bars, "Some unlimited argument"); + auto *bar = app.add_option("--bar", bars, "Some unlimited argument"); app.add_flag("--z,--x", "Random other flags"); @@ -33,7 +33,7 @@ int main(int argc, char **argv) { std::reverse(std::begin(bars), std::end(bars)); std::vector> keyval; - for(auto option : app.parse_order()) { + for(auto *option : app.parse_order()) { if(option == foo) { keyval.emplace_back("foo", foos.back()); foos.pop_back(); diff --git a/examples/modhelp.cpp b/examples/modhelp.cpp index ed66026..ac2ba17 100644 --- a/examples/modhelp.cpp +++ b/examples/modhelp.cpp @@ -16,7 +16,7 @@ Note that this will not shortcut `->required` and other similar options.)raw"}; test.set_help_flag(); // Add custom flag that activates help - auto help = test.add_flag("-h,--help", "Request help"); + auto *help = test.add_flag("-h,--help", "Request help"); std::string some_option; test.add_option("-a", some_option, "Some description"); diff --git a/examples/option_groups.cpp b/examples/option_groups.cpp index 47723fb..9799bdc 100644 --- a/examples/option_groups.cpp +++ b/examples/option_groups.cpp @@ -13,8 +13,8 @@ int main(int argc, char **argv) { CLI::App app("data output specification"); app.set_help_all_flag("--help-all", "Expand all help"); - auto format = app.add_option_group("output_format", "formatting type for output"); - auto target = app.add_option_group("output target", "target location for the output"); + auto *format = app.add_option_group("output_format", "formatting type for output"); + auto *target = app.add_option_group("output target", "target location for the output"); bool csv{false}; bool human{false}; bool binary{false}; diff --git a/examples/positional_arity.cpp b/examples/positional_arity.cpp index 16259c1..e8c45c4 100644 --- a/examples/positional_arity.cpp +++ b/examples/positional_arity.cpp @@ -12,8 +12,8 @@ int main(int argc, char **argv) { CLI::App app("test for positional arity"); - auto numbers = app.add_option_group("numbers", "specify key numbers"); - auto files = app.add_option_group("files", "specify files"); + auto *numbers = app.add_option_group("numbers", "specify key numbers"); + auto *files = app.add_option_group("files", "specify files"); int num1{-1}, num2{-1}; numbers->add_option("num1", num1, "first number"); numbers->add_option("num2", num2, "second number"); diff --git a/examples/prefix_command.cpp b/examples/prefix_command.cpp index 0e2f041..6163941 100644 --- a/examples/prefix_command.cpp +++ b/examples/prefix_command.cpp @@ -27,7 +27,7 @@ int main(int argc, char **argv) { std::cout << std::endl << "Remaining commands: "; - for(auto com : more_comms) + for(const auto &com : more_comms) std::cout << com << " "; std::cout << std::endl; diff --git a/examples/ranges.cpp b/examples/ranges.cpp index 4860b15..42b1659 100644 --- a/examples/ranges.cpp +++ b/examples/ranges.cpp @@ -15,7 +15,7 @@ int main(int argc, char **argv) { std::vector range; app.add_option("--range,-R", range, "A range")->expected(-2); - auto ogroup = app.add_option_group("min_max_step", "set the min max and step"); + auto *ogroup = app.add_option_group("min_max_step", "set the min max and step"); int min{0}, max{0}, step{1}; ogroup->add_option("--min,-m", min, "The minimum")->required(); ogroup->add_option("--max,-M", max, "The maximum")->required(); diff --git a/examples/retired.cpp b/examples/retired.cpp index 920f19f..0a3a5fb 100644 --- a/examples/retired.cpp +++ b/examples/retired.cpp @@ -14,10 +14,10 @@ int main(int argc, char **argv) { CLI::App app("example for retired/deprecated options"); std::vector x; - auto opt1 = app.add_option("--retired_option2", x); + auto *opt1 = app.add_option("--retired_option2", x); std::pair y; - auto opt2 = app.add_option("--deprecate", y); + auto *opt2 = app.add_option("--deprecate", y); app.add_option("--not_deprecated", x); diff --git a/examples/shapes.cpp b/examples/shapes.cpp index 16a7c17..d9f47ca 100644 --- a/examples/shapes.cpp +++ b/examples/shapes.cpp @@ -13,7 +13,7 @@ int main(int argc, char **argv) { CLI::App app("load shapes"); app.set_help_all_flag("--help-all"); - auto circle = app.add_subcommand("circle", "draw a circle")->immediate_callback(); + auto *circle = app.add_subcommand("circle", "draw a circle")->immediate_callback(); double radius{0.0}; int circle_counter{0}; circle->callback([&radius, &circle_counter] { @@ -23,7 +23,7 @@ int main(int argc, char **argv) { circle->add_option("radius", radius, "the radius of the circle")->required(); - auto rect = app.add_subcommand("rectangle", "draw a rectangle")->immediate_callback(); + auto *rect = app.add_subcommand("rectangle", "draw a rectangle")->immediate_callback(); double edge1{0.0}; double edge2{0.0}; int rect_counter{0}; @@ -39,7 +39,7 @@ int main(int argc, char **argv) { rect->add_option("edge1", edge1, "the first edge length of the rectangle")->required(); rect->add_option("edge2", edge2, "the second edge length of the rectangle"); - auto tri = app.add_subcommand("triangle", "draw a rectangle")->immediate_callback(); + auto *tri = app.add_subcommand("triangle", "draw a rectangle")->immediate_callback(); std::vector sides; int tri_counter = 0; tri->callback([&sides, &tri_counter] { diff --git a/examples/subcom_in_files/subcommand_a.cpp b/examples/subcom_in_files/subcommand_a.cpp index 02e8841..9ad65e0 100644 --- a/examples/subcom_in_files/subcommand_a.cpp +++ b/examples/subcom_in_files/subcommand_a.cpp @@ -15,7 +15,7 @@ void setup_subcommand_a(CLI::App &app) { // Create the option and subcommand objects. auto opt = std::make_shared(); - auto sub = app.add_subcommand("subcommand_a", "performs subcommand a"); + auto *sub = app.add_subcommand("subcommand_a", "performs subcommand a"); // Add options to sub, binding them to opt. sub->add_option("-f,--file", opt->file, "File name")->required(); diff --git a/examples/subcom_partitioned.cpp b/examples/subcom_partitioned.cpp index 109349d..493ac0e 100644 --- a/examples/subcom_partitioned.cpp +++ b/examples/subcom_partitioned.cpp @@ -11,7 +11,7 @@ #include int main(int argc, char **argv) { - CLI::AutoTimer("This is a timer"); + CLI::AutoTimer give_me_a_name("This is a timer"); CLI::App app("K3Pi goofit fitter"); diff --git a/examples/subcommands.cpp b/examples/subcommands.cpp index 5eabdc6..44d4df9 100644 --- a/examples/subcommands.cpp +++ b/examples/subcommands.cpp @@ -28,7 +28,7 @@ int main(int argc, char **argv) { std::cout << "Working on --count from stop: " << s->count() << ", direct count: " << stop->count("--count") << std::endl; std::cout << "Count of --random flag: " << app.count("--random") << std::endl; - for(auto subcom : app.get_subcommands()) + for(auto *subcom : app.get_subcommands()) std::cout << "Subcommand: " << subcom->get_name() << std::endl; return 0; diff --git a/examples/testEXE.cpp b/examples/testEXE.cpp index b69e154..b63fa94 100644 --- a/examples/testEXE.cpp +++ b/examples/testEXE.cpp @@ -17,7 +17,7 @@ int main(int argc, const char *argv[]) { app.add_option("-v", logLevel, "level"); - auto subcom = app.add_subcommand("sub", "")->fallthrough(); + auto *subcom = app.add_subcommand("sub", "")->fallthrough(); subcom->preparse_callback([&app](size_t) { app.get_subcommand("sub")->add_option_group("group"); }); CLI11_PARSE(app, argc, argv); diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 1ae2020..7c8b766 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -374,7 +374,7 @@ class App { if(parent_ != nullptr) { auto oname = name_; name_ = app_name; - auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent()); + const auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent()); if(!res.empty()) { name_ = oname; throw(OptionAlreadyAdded(app_name + " conflicts with existing subcommand names")); @@ -393,7 +393,7 @@ class App { } if(parent_ != nullptr) { aliases_.push_back(app_name); - auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent()); + const auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent()); if(!res.empty()) { aliases_.pop_back(); throw(OptionAlreadyAdded("alias already matches an existing subcommand: " + app_name)); @@ -504,7 +504,7 @@ class App { if(value && !ignore_case_) { ignore_case_ = true; auto *p = (parent_ != nullptr) ? _get_fallthrough_parent() : this; - auto &match = _compare_subcommand_names(*this, *p); + const auto &match = _compare_subcommand_names(*this, *p); if(!match.empty()) { ignore_case_ = false; // we are throwing so need to be exception invariant throw OptionAlreadyAdded("ignore case would cause subcommand name conflicts: " + match); @@ -538,7 +538,7 @@ class App { if(value && !ignore_underscore_) { ignore_underscore_ = true; auto *p = (parent_ != nullptr) ? _get_fallthrough_parent() : this; - auto &match = _compare_subcommand_names(*this, *p); + const auto &match = _compare_subcommand_names(*this, *p); if(!match.empty()) { ignore_underscore_ = false; throw OptionAlreadyAdded("ignore underscore would cause subcommand name conflicts: " + match); @@ -567,7 +567,7 @@ class App { } /// Check to see if this subcommand was parsed, true only if received on command line. - bool parsed() const { return parsed_ > 0; } + CLI11_NODISCARD bool parsed() const { return parsed_ > 0; } /// Get the OptionDefault object, to set option defaults OptionDefaults *option_defaults() { return &option_defaults_; } @@ -622,7 +622,7 @@ class App { } // we know something matches now find what it is so we can produce more error information for(auto &opt : options_) { - auto &matchname = opt->matching_name(myopt); + const auto &matchname = opt->matching_name(myopt); if(!matchname.empty()) { throw(OptionAlreadyAdded("added option matched existing option name: " + matchname)); } @@ -785,7 +785,7 @@ class App { private: /// Internal function for adding a flag Option *_add_flag_internal(std::string flag_name, CLI::callback_t fun, std::string flag_description) { - Option *opt; + Option *opt = nullptr; if(detail::has_default_flag_values(flag_name)) { // check for default values and if it has them auto flag_defaults = detail::get_default_flag_values(flag_name); @@ -956,7 +956,7 @@ class App { throw IncorrectConstruction("option group names may not contain newlines or null characters"); } auto option_group = std::make_shared(std::move(group_description), group_name, this); - auto ptr = option_group.get(); + auto *ptr = option_group.get(); // move to App_p for overload resolution on older gcc versions App_p app_ptr = std::dynamic_pointer_cast(option_group); add_subcommand(std::move(app_ptr)); @@ -990,8 +990,8 @@ class App { App *add_subcommand(CLI::App_p subcom) { if(!subcom) throw IncorrectConstruction("passed App is not valid"); - auto ckapp = (name_.empty() && parent_ != nullptr) ? _get_fallthrough_parent() : this; - auto &mstrg = _compare_subcommand_names(*subcom, *ckapp); + auto *ckapp = (name_.empty() && parent_ != nullptr) ? _get_fallthrough_parent() : this; + const auto &mstrg = _compare_subcommand_names(*subcom, *ckapp); if(!mstrg.empty()) { throw(OptionAlreadyAdded("subcommand name or alias matches existing subcommand: " + mstrg)); } @@ -1028,14 +1028,14 @@ class App { } /// Check to see if a subcommand is part of this command (text version) - App *get_subcommand(std::string subcom) const { - auto subc = _find_subcommand(subcom, false, false); + CLI11_NODISCARD App *get_subcommand(std::string subcom) const { + auto *subc = _find_subcommand(subcom, false, false); if(subc == nullptr) throw OptionNotFound(subcom); return subc; } /// Get a pointer to subcommand by index - App *get_subcommand(int index = 0) const { + CLI11_NODISCARD App *get_subcommand(int index = 0) const { if(index >= 0) { auto uindex = static_cast(index); if(uindex < subcommands_.size()) @@ -1055,7 +1055,7 @@ class App { } /// Check to see if a subcommand is part of this command (text version) - CLI::App_p get_subcommand_ptr(std::string subcom) const { + CLI11_NODISCARD CLI::App_p get_subcommand_ptr(std::string subcom) const { for(const App_p &subcomptr : subcommands_) if(subcomptr->check_name(subcom)) return subcomptr; @@ -1063,7 +1063,7 @@ class App { } /// Get an owning pointer to subcommand by index - CLI::App_p get_subcommand_ptr(int index = 0) const { + CLI11_NODISCARD CLI::App_p get_subcommand_ptr(int index = 0) const { if(index >= 0) { auto uindex = static_cast(index); if(uindex < subcommands_.size()) @@ -1073,7 +1073,7 @@ class App { } /// Check to see if an option group is part of this App - App *get_option_group(std::string group_name) const { + CLI11_NODISCARD App *get_option_group(std::string group_name) const { for(const App_p &app : subcommands_) { if(app->name_.empty() && app->group_ == group_name) { return app.get(); @@ -1085,16 +1085,16 @@ class App { /// No argument version of count counts the number of times this subcommand was /// passed in. The main app will return 1. Unnamed subcommands will also return 1 unless /// otherwise modified in a callback - std::size_t count() const { return parsed_; } + CLI11_NODISCARD std::size_t count() const { return parsed_; } /// Get a count of all the arguments processed in options and subcommands, this excludes arguments which were /// treated as extras. - std::size_t count_all() const { + CLI11_NODISCARD std::size_t count_all() const { std::size_t cnt{0}; - for(auto &opt : options_) { + for(const auto &opt : options_) { cnt += opt->count(); } - for(auto &sub : subcommands_) { + for(const auto &sub : subcommands_) { cnt += sub->count_all(); } if(!get_name().empty()) { // for named subcommands add the number of times the subcommand was called @@ -1345,11 +1345,11 @@ class App { ///@{ /// Counts the number of times the given option was passed. - std::size_t count(std::string option_name) const { return get_option(option_name)->count(); } + CLI11_NODISCARD std::size_t count(std::string option_name) const { return get_option(option_name)->count(); } /// Get a subcommand pointer list to the currently selected subcommands (after parsing by default, in command /// line order; use parsed = false to get the original definition list.) - std::vector get_subcommands() const { return parsed_subcommands_; } + CLI11_NODISCARD std::vector get_subcommands() const { return parsed_subcommands_; } /// Get a filtered subcommand pointer list from the original definition list. An empty function will provide all /// subcommands (const) @@ -1393,7 +1393,9 @@ class App { } /// Check with name instead of pointer to see if subcommand was selected - bool got_subcommand(std::string subcommand_name) const { return get_subcommand(subcommand_name)->parsed_ > 0; } + CLI11_NODISCARD bool got_subcommand(std::string subcommand_name) const { + return get_subcommand(subcommand_name)->parsed_ > 0; + } /// Sets excluded options for the subcommand App *excludes(Option *opt) { @@ -1455,7 +1457,7 @@ class App { if(iterator == std::end(exclude_subcommands_)) { return false; } - auto other_app = *iterator; + auto *other_app = *iterator; exclude_subcommands_.erase(iterator); other_app->remove_excludes(this); return true; @@ -1497,13 +1499,13 @@ class App { } /// Produce a string that could be read in as a config of the current values of the App. Set default_also to /// include default arguments. write_descriptions will print a description for the App and for each option. - std::string config_to_str(bool default_also = false, bool write_description = false) const { + CLI11_NODISCARD std::string config_to_str(bool default_also = false, bool write_description = false) const { return config_formatter_->to_config(this, default_also, write_description, ""); } /// Makes a help message, using the currently configured formatter /// Will only do one subcommand at a time - std::string help(std::string prev = "", AppFormatMode mode = AppFormatMode::Normal) const { + CLI11_NODISCARD std::string help(std::string prev = "", AppFormatMode mode = AppFormatMode::Normal) const { if(prev.empty()) prev = get_name(); else @@ -1518,7 +1520,7 @@ class App { } /// Displays a version string - std::string version() const { + CLI11_NODISCARD std::string version() const { std::string val; if(version_ptr_ != nullptr) { auto rv = version_ptr_->results(); @@ -1539,13 +1541,13 @@ class App { ///@{ /// Access the formatter - std::shared_ptr get_formatter() const { return formatter_; } + CLI11_NODISCARD std::shared_ptr get_formatter() const { return formatter_; } /// Access the config formatter - std::shared_ptr get_config_formatter() const { return config_formatter_; } + CLI11_NODISCARD std::shared_ptr get_config_formatter() const { return config_formatter_; } /// Access the config formatter as a configBase pointer - std::shared_ptr get_config_formatter_base() const { + CLI11_NODISCARD std::shared_ptr get_config_formatter_base() const { // This is safer as a dynamic_cast if we have RTTI, as Config -> ConfigBase #if CLI11_USE_STATIC_RTTI == 0 return std::dynamic_pointer_cast(config_formatter_); @@ -1555,7 +1557,7 @@ class App { } /// Get the app or subcommand description - std::string get_description() const { return description_; } + CLI11_NODISCARD std::string get_description() const { return description_; } /// Set the description of the app App *description(std::string app_description) { @@ -1606,7 +1608,7 @@ class App { for(auto &subc : subcommands_) { // also check down into nameless subcommands if(subc->get_name().empty()) { - auto opt = subc->get_option_no_throw(option_name); + auto *opt = subc->get_option_no_throw(option_name); if(opt != nullptr) { return opt; } @@ -1616,7 +1618,7 @@ class App { } /// Get an option by name (noexcept const version) - const Option *get_option_no_throw(std::string option_name) const noexcept { + CLI11_NODISCARD const Option *get_option_no_throw(std::string option_name) const noexcept { for(const Option_p &opt : options_) { if(opt->check_name(option_name)) { return opt.get(); @@ -1625,7 +1627,7 @@ class App { for(const auto &subc : subcommands_) { // also check down into nameless subcommands if(subc->get_name().empty()) { - auto opt = subc->get_option_no_throw(option_name); + auto *opt = subc->get_option_no_throw(option_name); if(opt != nullptr) { return opt; } @@ -1635,8 +1637,8 @@ class App { } /// Get an option by name - const Option *get_option(std::string option_name) const { - auto opt = get_option_no_throw(option_name); + CLI11_NODISCARD const Option *get_option(std::string option_name) const { + const auto *opt = get_option_no_throw(option_name); if(opt == nullptr) { throw OptionNotFound(option_name); } @@ -1645,7 +1647,7 @@ class App { /// Get an option by name (non-const version) Option *get_option(std::string option_name) { - auto opt = get_option_no_throw(option_name); + auto *opt = get_option_no_throw(option_name); if(opt == nullptr) { throw OptionNotFound(option_name); } @@ -1659,104 +1661,106 @@ class App { const Option *operator[](const char *option_name) const { return get_option(option_name); } /// Check the status of ignore_case - bool get_ignore_case() const { return ignore_case_; } + CLI11_NODISCARD bool get_ignore_case() const { return ignore_case_; } /// Check the status of ignore_underscore - bool get_ignore_underscore() const { return ignore_underscore_; } + CLI11_NODISCARD bool get_ignore_underscore() const { return ignore_underscore_; } /// Check the status of fallthrough - bool get_fallthrough() const { return fallthrough_; } + CLI11_NODISCARD bool get_fallthrough() const { return fallthrough_; } /// Check the status of the allow windows style options - bool get_allow_windows_style_options() const { return allow_windows_style_options_; } + CLI11_NODISCARD bool get_allow_windows_style_options() const { return allow_windows_style_options_; } /// Check the status of the allow windows style options - bool get_positionals_at_end() const { return positionals_at_end_; } + CLI11_NODISCARD bool get_positionals_at_end() const { return positionals_at_end_; } /// Check the status of the allow windows style options - bool get_configurable() const { return configurable_; } + CLI11_NODISCARD bool get_configurable() const { return configurable_; } /// Get the group of this subcommand - const std::string &get_group() const { return group_; } + CLI11_NODISCARD const std::string &get_group() const { return group_; } /// Generate and return the footer. - std::string get_footer() const { return (footer_callback_) ? footer_callback_() + '\n' + footer_ : footer_; } + CLI11_NODISCARD std::string get_footer() const { + return (footer_callback_) ? footer_callback_() + '\n' + footer_ : footer_; + } /// Get the required min subcommand value - std::size_t get_require_subcommand_min() const { return require_subcommand_min_; } + CLI11_NODISCARD std::size_t get_require_subcommand_min() const { return require_subcommand_min_; } /// Get the required max subcommand value - std::size_t get_require_subcommand_max() const { return require_subcommand_max_; } + CLI11_NODISCARD std::size_t get_require_subcommand_max() const { return require_subcommand_max_; } /// Get the required min option value - std::size_t get_require_option_min() const { return require_option_min_; } + CLI11_NODISCARD std::size_t get_require_option_min() const { return require_option_min_; } /// Get the required max option value - std::size_t get_require_option_max() const { return require_option_max_; } + CLI11_NODISCARD std::size_t get_require_option_max() const { return require_option_max_; } /// Get the prefix command status - bool get_prefix_command() const { return prefix_command_; } + CLI11_NODISCARD bool get_prefix_command() const { return prefix_command_; } /// Get the status of allow extras - bool get_allow_extras() const { return allow_extras_; } + CLI11_NODISCARD bool get_allow_extras() const { return allow_extras_; } /// Get the status of required - bool get_required() const { return required_; } + CLI11_NODISCARD bool get_required() const { return required_; } /// Get the status of disabled - bool get_disabled() const { return disabled_; } + CLI11_NODISCARD bool get_disabled() const { return disabled_; } /// Get the status of silence - bool get_silent() const { return silent_; } + CLI11_NODISCARD bool get_silent() const { return silent_; } /// Get the status of disabled - bool get_immediate_callback() const { return immediate_callback_; } + CLI11_NODISCARD bool get_immediate_callback() const { return immediate_callback_; } /// Get the status of disabled by default - bool get_disabled_by_default() const { return (default_startup == startup_mode::disabled); } + CLI11_NODISCARD bool get_disabled_by_default() const { return (default_startup == startup_mode::disabled); } /// Get the status of disabled by default - bool get_enabled_by_default() const { return (default_startup == startup_mode::enabled); } + CLI11_NODISCARD bool get_enabled_by_default() const { return (default_startup == startup_mode::enabled); } /// Get the status of validating positionals - bool get_validate_positionals() const { return validate_positionals_; } + CLI11_NODISCARD bool get_validate_positionals() const { return validate_positionals_; } /// Get the status of validating optional vector arguments - bool get_validate_optional_arguments() const { return validate_optional_arguments_; } + CLI11_NODISCARD bool get_validate_optional_arguments() const { return validate_optional_arguments_; } /// Get the status of allow extras - config_extras_mode get_allow_config_extras() const { return allow_config_extras_; } + CLI11_NODISCARD config_extras_mode get_allow_config_extras() const { return allow_config_extras_; } /// Get a pointer to the help flag. Option *get_help_ptr() { return help_ptr_; } /// Get a pointer to the help flag. (const) - const Option *get_help_ptr() const { return help_ptr_; } + CLI11_NODISCARD const Option *get_help_ptr() const { return help_ptr_; } /// Get a pointer to the help all flag. (const) - const Option *get_help_all_ptr() const { return help_all_ptr_; } + CLI11_NODISCARD const Option *get_help_all_ptr() const { return help_all_ptr_; } /// Get a pointer to the config option. Option *get_config_ptr() { return config_ptr_; } /// Get a pointer to the config option. (const) - const Option *get_config_ptr() const { return config_ptr_; } + CLI11_NODISCARD const Option *get_config_ptr() const { return config_ptr_; } /// Get a pointer to the version option. Option *get_version_ptr() { return version_ptr_; } /// Get a pointer to the version option. (const) - const Option *get_version_ptr() const { return version_ptr_; } + CLI11_NODISCARD const Option *get_version_ptr() const { return version_ptr_; } /// Get the parent of this subcommand (or nullptr if main app) App *get_parent() { return parent_; } /// Get the parent of this subcommand (or nullptr if main app) (const version) - const App *get_parent() const { return parent_; } + CLI11_NODISCARD const App *get_parent() const { return parent_; } /// Get the name of the current app - const std::string &get_name() const { return name_; } + CLI11_NODISCARD const std::string &get_name() const { return name_; } /// Get the aliases of the current app - const std::vector &get_aliases() const { return aliases_; } + CLI11_NODISCARD const std::vector &get_aliases() const { return aliases_; } /// clear all the aliases of the current App App *clear_aliases() { @@ -1765,7 +1769,7 @@ class App { } /// Get a display name for an app - std::string get_display_name(bool with_aliases = false) const { + CLI11_NODISCARD std::string get_display_name(bool with_aliases = false) const { if(name_.empty()) { return std::string("[Option Group: ") + get_group() + "]"; } @@ -1782,7 +1786,7 @@ class App { } /// Check the name, case insensitive and underscore insensitive if set - bool check_name(std::string name_to_check) const { + CLI11_NODISCARD bool check_name(std::string name_to_check) const { std::string local_name = name_; if(ignore_underscore_) { local_name = detail::remove_underscore(name_); @@ -1796,7 +1800,7 @@ class App { if(local_name == name_to_check) { return true; } - for(auto les : aliases_) { + for(auto les : aliases_) { // NOLINT(performance-for-range-copy) if(ignore_underscore_) { les = detail::remove_underscore(les); } @@ -1811,7 +1815,7 @@ class App { } /// Get the groups available directly from this option (in order) - std::vector get_groups() const { + CLI11_NODISCARD std::vector get_groups() const { std::vector groups; for(const Option_p &opt : options_) { @@ -1825,10 +1829,10 @@ class App { } /// This gets a vector of pointers with the original parse order - const std::vector