brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.5 KiB · 6fbd392 Raw
235 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "UnusedReturnValueCheck.h"10#include "../utils/Matchers.h"11#include "../utils/OptionsUtils.h"12#include "clang/ASTMatchers/ASTMatchFinder.h"13#include "clang/ASTMatchers/ASTMatchers.h"14#include "clang/Basic/OperatorKinds.h"15 16using namespace clang::ast_matchers;17using namespace clang::ast_matchers::internal;18 19namespace clang::tidy::bugprone {20 21namespace {22 23// Matches functions that are instantiated from a class template member function24// matching InnerMatcher. Functions not instantiated from a class template25// member function are matched directly with InnerMatcher.26AST_MATCHER_P(FunctionDecl, isInstantiatedFrom, Matcher<FunctionDecl>,27              InnerMatcher) {28  const FunctionDecl *InstantiatedFrom =29      Node.getInstantiatedFromMemberFunction();30  return InnerMatcher.matches(InstantiatedFrom ? *InstantiatedFrom : Node,31                              Finder, Builder);32}33 34constexpr std::initializer_list<OverloadedOperatorKind>35    AssignmentOverloadedOperatorKinds = {36        OO_Equal,      OO_PlusEqual,     OO_MinusEqual,          OO_StarEqual,37        OO_SlashEqual, OO_PercentEqual,  OO_CaretEqual,          OO_AmpEqual,38        OO_PipeEqual,  OO_LessLessEqual, OO_GreaterGreaterEqual, OO_PlusPlus,39        OO_MinusMinus};40 41AST_MATCHER(FunctionDecl, isAssignmentOverloadedOperator) {42  return llvm::is_contained(AssignmentOverloadedOperatorKinds,43                            Node.getOverloadedOperator());44}45} // namespace46 47UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name,48                                               ClangTidyContext *Context)49    : ClangTidyCheck(Name, Context),50      CheckedFunctions(utils::options::parseStringList(51          Options.get("CheckedFunctions", "^::std::async$;"52                                          "^::std::launder$;"53                                          "^::std::remove$;"54                                          "^::std::remove_if$;"55                                          "^::std::unique$;"56                                          "^::std::unique_ptr::release$;"57                                          "^::std::basic_string::empty$;"58                                          "^::std::vector::empty$;"59                                          "^::std::back_inserter$;"60                                          "^::std::distance$;"61                                          "^::std::find$;"62                                          "^::std::find_if$;"63                                          "^::std::inserter$;"64                                          "^::std::lower_bound$;"65                                          "^::std::make_pair$;"66                                          "^::std::map::count$;"67                                          "^::std::map::find$;"68                                          "^::std::map::lower_bound$;"69                                          "^::std::multimap::equal_range$;"70                                          "^::std::multimap::upper_bound$;"71                                          "^::std::set::count$;"72                                          "^::std::set::find$;"73                                          "^::std::setfill$;"74                                          "^::std::setprecision$;"75                                          "^::std::setw$;"76                                          "^::std::upper_bound$;"77                                          "^::std::vector::at$;"78                                          // C standard library79                                          "^::bsearch$;"80                                          "^::ferror$;"81                                          "^::feof$;"82                                          "^::isalnum$;"83                                          "^::isalpha$;"84                                          "^::isblank$;"85                                          "^::iscntrl$;"86                                          "^::isdigit$;"87                                          "^::isgraph$;"88                                          "^::islower$;"89                                          "^::isprint$;"90                                          "^::ispunct$;"91                                          "^::isspace$;"92                                          "^::isupper$;"93                                          "^::iswalnum$;"94                                          "^::iswprint$;"95                                          "^::iswspace$;"96                                          "^::isxdigit$;"97                                          "^::memchr$;"98                                          "^::memcmp$;"99                                          "^::strcmp$;"100                                          "^::strcoll$;"101                                          "^::strncmp$;"102                                          "^::strpbrk$;"103                                          "^::strrchr$;"104                                          "^::strspn$;"105                                          "^::strstr$;"106                                          "^::wcscmp$;"107                                          // POSIX108                                          "^::access$;"109                                          "^::bind$;"110                                          "^::connect$;"111                                          "^::difftime$;"112                                          "^::dlsym$;"113                                          "^::fnmatch$;"114                                          "^::getaddrinfo$;"115                                          "^::getopt$;"116                                          "^::htonl$;"117                                          "^::htons$;"118                                          "^::iconv_open$;"119                                          "^::inet_addr$;"120                                          "^::isascii$;"121                                          "^::isatty$;"122                                          "^::mmap$;"123                                          "^::newlocale$;"124                                          "^::openat$;"125                                          "^::pathconf$;"126                                          "^::pthread_equal$;"127                                          "^::pthread_getspecific$;"128                                          "^::pthread_mutex_trylock$;"129                                          "^::readdir$;"130                                          "^::readlink$;"131                                          "^::recvmsg$;"132                                          "^::regexec$;"133                                          "^::scandir$;"134                                          "^::semget$;"135                                          "^::setjmp$;"136                                          "^::shm_open$;"137                                          "^::shmget$;"138                                          "^::sigismember$;"139                                          "^::strcasecmp$;"140                                          "^::strsignal$;"141                                          "^::ttyname$"))),142      CheckedReturnTypes(utils::options::parseStringList(143          Options.get("CheckedReturnTypes", "^::std::error_code$;"144                                            "^::std::error_condition$;"145                                            "^::std::errc$;"146                                            "^::std::expected$;"147                                            "^::boost::system::error_code$"))),148      AllowCastToVoid(Options.get("AllowCastToVoid", false)) {}149 150UnusedReturnValueCheck::UnusedReturnValueCheck(151    llvm::StringRef Name, ClangTidyContext *Context,152    std::vector<StringRef> CheckedFunctions)153    : UnusedReturnValueCheck(Name, Context, std::move(CheckedFunctions), {},154                             false) {}155 156UnusedReturnValueCheck::UnusedReturnValueCheck(157    llvm::StringRef Name, ClangTidyContext *Context,158    std::vector<StringRef> CheckedFunctions,159    std::vector<StringRef> CheckedReturnTypes, bool AllowCastToVoid)160    : ClangTidyCheck(Name, Context),161      CheckedFunctions(std::move(CheckedFunctions)),162      CheckedReturnTypes(std::move(CheckedReturnTypes)),163      AllowCastToVoid(AllowCastToVoid) {}164 165void UnusedReturnValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {166  Options.store(Opts, "CheckedFunctions",167                utils::options::serializeStringList(CheckedFunctions));168  Options.store(Opts, "CheckedReturnTypes",169                utils::options::serializeStringList(CheckedReturnTypes));170  Options.store(Opts, "AllowCastToVoid", AllowCastToVoid);171}172 173void UnusedReturnValueCheck::registerMatchers(MatchFinder *Finder) {174  auto MatchedDirectCallExpr =175      expr(callExpr(callee(functionDecl(176                        // Don't match copy or move assignment operator.177                        unless(isAssignmentOverloadedOperator()),178                        // Don't match void overloads of checked functions.179                        unless(returns(voidType())),180                        anyOf(isInstantiatedFrom(matchers::matchesAnyListedName(181                                  CheckedFunctions)),182                              returns(hasCanonicalType(hasDeclaration(183                                  namedDecl(matchers::matchesAnyListedName(184                                      CheckedReturnTypes)))))))))185               .bind("match"));186 187  auto CheckCastToVoid =188      AllowCastToVoid ? castExpr(unless(hasCastKind(CK_ToVoid))) : castExpr();189  auto MatchedCallExpr = expr(190      anyOf(MatchedDirectCallExpr,191            explicitCastExpr(unless(cxxFunctionalCastExpr()), CheckCastToVoid,192                             hasSourceExpression(MatchedDirectCallExpr))));193 194  auto UnusedInCompoundStmt =195      compoundStmt(forEach(MatchedCallExpr),196                   // The checker can't currently differentiate between the197                   // return statement and other statements inside GNU statement198                   // expressions, so disable the checker inside them to avoid199                   // false positives.200                   unless(hasParent(stmtExpr())));201  auto UnusedInIfStmt =202      ifStmt(eachOf(hasThen(MatchedCallExpr), hasElse(MatchedCallExpr)));203  auto UnusedInWhileStmt = whileStmt(hasBody(MatchedCallExpr));204  auto UnusedInDoStmt = doStmt(hasBody(MatchedCallExpr));205  auto UnusedInForStmt =206      forStmt(eachOf(hasLoopInit(MatchedCallExpr),207                     hasIncrement(MatchedCallExpr), hasBody(MatchedCallExpr)));208  auto UnusedInRangeForStmt = cxxForRangeStmt(hasBody(MatchedCallExpr));209  auto UnusedInCaseStmt = switchCase(forEach(MatchedCallExpr));210 211  Finder->addMatcher(212      stmt(anyOf(UnusedInCompoundStmt, UnusedInIfStmt, UnusedInWhileStmt,213                 UnusedInDoStmt, UnusedInForStmt, UnusedInRangeForStmt,214                 UnusedInCaseStmt)),215      this);216}217 218void UnusedReturnValueCheck::check(const MatchFinder::MatchResult &Result) {219  if (const auto *Matched = Result.Nodes.getNodeAs<CallExpr>("match")) {220    diag(Matched->getBeginLoc(),221         "the value returned by this function should not be disregarded; "222         "neglecting it may lead to errors")223        << Matched->getSourceRange();224 225    if (!AllowCastToVoid)226      return;227 228    diag(Matched->getBeginLoc(),229         "cast the expression to void to silence this warning",230         DiagnosticIDs::Note);231  }232}233 234} // namespace clang::tidy::bugprone235