diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h @@ -29,6 +29,8 @@ private: std::string CheckedFunctions; + std::string IncludedFunctions; + std::string ExcludedFunctions; }; } // namespace bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp @@ -30,116 +30,129 @@ Finder, Builder); } +const std::string DefaultCheckedFunctions = "::std::async;" + "::std::launder;" + "::std::remove;" + "::std::remove_if;" + "::std::unique;" + "::std::unique_ptr::release;" + "::std::basic_string::empty;" + "::std::vector::empty;" + "::std::back_inserter;" + "::std::distance;" + "::std::find;" + "::std::find_if;" + "::std::inserter;" + "::std::lower_bound;" + "::std::make_pair;" + "::std::map::count;" + "::std::map::find;" + "::std::map::lower_bound;" + "::std::multimap::equal_range;" + "::std::multimap::upper_bound;" + "::std::set::count;" + "::std::set::find;" + "::std::setfill;" + "::std::setprecision;" + "::std::setw;" + "::std::upper_bound;" + "::std::vector::at;" + // C standard library + "::bsearch;" + "::ferror;" + "::feof;" + "::isalnum;" + "::isalpha;" + "::isblank;" + "::iscntrl;" + "::isdigit;" + "::isgraph;" + "::islower;" + "::isprint;" + "::ispunct;" + "::isspace;" + "::isupper;" + "::iswalnum;" + "::iswprint;" + "::iswspace;" + "::isxdigit;" + "::memchr;" + "::memcmp;" + "::strcmp;" + "::strcoll;" + "::strncmp;" + "::strpbrk;" + "::strrchr;" + "::strspn;" + "::strstr;" + "::wcscmp;" + // POSIX + "::access;" + "::bind;" + "::connect;" + "::difftime;" + "::dlsym;" + "::fnmatch;" + "::getaddrinfo;" + "::getopt;" + "::htonl;" + "::htons;" + "::iconv_open;" + "::inet_addr;" + "::isascii;" + "::isatty;" + "::mmap;" + "::newlocale;" + "::openat;" + "::pathconf;" + "::pthread_equal;" + "::pthread_getspecific;" + "::pthread_mutex_trylock;" + "::readdir;" + "::readlink;" + "::recvmsg;" + "::regexec;" + "::scandir;" + "::semget;" + "::setjmp;" + "::shm_open;" + "::shmget;" + "::sigismember;" + "::strcasecmp;" + "::strsignal;" + "::ttyname"; + } // namespace UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - CheckedFunctions(Options.get("CheckedFunctions", - "::std::async;" - "::std::launder;" - "::std::remove;" - "::std::remove_if;" - "::std::unique;" - "::std::unique_ptr::release;" - "::std::basic_string::empty;" - "::std::vector::empty;" - "::std::back_inserter;" - "::std::distance;" - "::std::find;" - "::std::find_if;" - "::std::inserter;" - "::std::lower_bound;" - "::std::make_pair;" - "::std::map::count;" - "::std::map::find;" - "::std::map::lower_bound;" - "::std::multimap::equal_range;" - "::std::multimap::upper_bound;" - "::std::set::count;" - "::std::set::find;" - "::std::setfill;" - "::std::setprecision;" - "::std::setw;" - "::std::upper_bound;" - "::std::vector::at;" - // C standard library - "::bsearch;" - "::ferror;" - "::feof;" - "::isalnum;" - "::isalpha;" - "::isblank;" - "::iscntrl;" - "::isdigit;" - "::isgraph;" - "::islower;" - "::isprint;" - "::ispunct;" - "::isspace;" - "::isupper;" - "::iswalnum;" - "::iswprint;" - "::iswspace;" - "::isxdigit;" - "::memchr;" - "::memcmp;" - "::strcmp;" - "::strcoll;" - "::strncmp;" - "::strpbrk;" - "::strrchr;" - "::strspn;" - "::strstr;" - "::wcscmp;" - // POSIX - "::access;" - "::bind;" - "::connect;" - "::difftime;" - "::dlsym;" - "::fnmatch;" - "::getaddrinfo;" - "::getopt;" - "::htonl;" - "::htons;" - "::iconv_open;" - "::inet_addr;" - "::isascii;" - "::isatty;" - "::mmap;" - "::newlocale;" - "::openat;" - "::pathconf;" - "::pthread_equal;" - "::pthread_getspecific;" - "::pthread_mutex_trylock;" - "::readdir;" - "::readlink;" - "::recvmsg;" - "::regexec;" - "::scandir;" - "::semget;" - "::setjmp;" - "::shm_open;" - "::shmget;" - "::sigismember;" - "::strcasecmp;" - "::strsignal;" - "::ttyname")) {} + CheckedFunctions( + Options.get("CheckedFunctions", DefaultCheckedFunctions)), + IncludedFunctions(Options.get("IncludedFunctions", "")), + ExcludedFunctions(Options.get("ExcludedFunctions", "")) {} void UnusedReturnValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "CheckedFunctions", CheckedFunctions); + Options.store(Opts, "IncludedFunctions", IncludedFunctions); + Options.store(Opts, "ExcludedFunctions", ExcludedFunctions); } void UnusedReturnValueCheck::registerMatchers(MatchFinder *Finder) { auto FunVec = utils::options::parseStringList(CheckedFunctions); + std::set Functions(FunVec.begin(), FunVec.end()); + FunVec = utils::options::parseStringList(IncludedFunctions); + Functions.insert(FunVec.begin(), FunVec.end()); + FunVec = utils::options::parseStringList(ExcludedFunctions); + for (const std::string &Str : FunVec) + Functions.erase(Str); + auto MatchedCallExpr = expr(ignoringImplicit(ignoringParenImpCasts( callExpr(callee(functionDecl( // Don't match void overloads of checked functions. unless(returns(voidType())), - isInstantiatedFrom(hasAnyName( - std::vector(FunVec.begin(), FunVec.end())))))) + isInstantiatedFrom(hasAnyName(std::vector( + Functions.begin(), Functions.end())))))) .bind("match")))); auto UnusedInCompoundStmt = diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-unused-return-value-custom.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone-unused-return-value-custom.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-unused-return-value-custom.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-unused-return-value-custom.cpp @@ -1,7 +1,11 @@ // RUN: %check_clang_tidy %s bugprone-unused-return-value %t \ // RUN: -config='{CheckOptions: \ // RUN: [{key: bugprone-unused-return-value.CheckedFunctions, \ -// RUN: value: "::fun;::ns::Outer::Inner::memFun;::ns::Type::staticFun;::ns::ClassTemplate::memFun;::ns::ClassTemplate::staticFun"}]}' \ +// RUN: value: "::fun;::ns::Outer::Inner::memFun;::ns::Type::staticFun;::ns::ClassTemplate::memFun;::ns::ClassTemplate::staticFun;::excludedFun"}, \ +// RUN: {key: bugprone-unused-return-value.IncludedFunctions, \ +// RUN: value: "::includedFun;::excludedFun"}, \ +// RUN: {key: bugprone-unused-return-value.ExcludedFunctions, \ +// RUN: value: "::excludedFun"}]}' \ // RUN: -- namespace std { @@ -44,6 +48,8 @@ int fun(); void fun(int); +int includedFun(); +int excludedFun(); void warning() { fun(); @@ -81,6 +87,10 @@ ns::ClassTemplate::staticFun(); // CHECK-NOTES: [[@LINE-1]]:3: warning: the value {{.*}} should be used // CHECK-NOTES: [[@LINE-2]]:3: note: cast {{.*}} this warning + + includedFun(); + // CHECK-NOTES: [[@LINE-1]]:3: warning: the value {{.*}} should be used + // CHECK-NOTES: [[@LINE-2]]:3: note: cast {{.*}} this warning } void noWarning() { @@ -105,4 +115,7 @@ ns::Type ObjB3; ObjB3.memFun(); + + // no warning on function that is specified as excluded and as to be checked + excludedFun(); }