12#include "clang/ASTMatchers/ASTMatchFinder.h"
13#include "clang/ASTMatchers/ASTMatchers.h"
14#include "clang/Basic/OperatorKinds.h"
17using namespace clang::ast_matchers::internal;
26AST_MATCHER_P(FunctionDecl, isInstantiatedFrom, Matcher<FunctionDecl>,
28 const FunctionDecl *InstantiatedFrom =
29 Node.getInstantiatedFromMemberFunction();
30 return InnerMatcher.matches(InstantiatedFrom ? *InstantiatedFrom : Node,
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,
41AST_MATCHER(FunctionDecl, isAssignmentOverloadedOperator) {
42 return llvm::is_contained(AssignmentOverloadedOperatorKinds,
43 Node.getOverloadedOperator());
48 ClangTidyContext *Context)
49 : ClangTidyCheck(Name, Context),
51 Options.get(
"CheckedFunctions",
"^::std::async$;"
56 "^::std::unique_ptr::release$;"
57 "^::std::basic_string::empty$;"
58 "^::std::vector::empty$;"
59 "^::std::back_inserter$;"
64 "^::std::lower_bound$;"
66 "^::std::map::count$;"
68 "^::std::map::lower_bound$;"
69 "^::std::multimap::equal_range$;"
70 "^::std::multimap::upper_bound$;"
71 "^::std::set::count$;"
74 "^::std::setprecision$;"
76 "^::std::upper_bound$;"
77 "^::std::vector::at$;"
127 "^::pthread_getspecific$;"
128 "^::pthread_mutex_trylock$;"
143 Options.get(
"CheckedReturnTypes",
"^::std::error_code$;"
144 "^::std::error_condition$;"
147 "^::boost::system::error_code$"))),
148 AllowCastToVoid(Options.get(
"AllowCastToVoid", false)) {}
150UnusedReturnValueCheck::UnusedReturnValueCheck(
151 llvm::StringRef Name, ClangTidyContext *Context,
152 std::vector<StringRef> CheckedFunctions)
153 : UnusedReturnValueCheck(Name, Context, std::
move(CheckedFunctions), {},
156UnusedReturnValueCheck::UnusedReturnValueCheck(
157 llvm::StringRef Name, ClangTidyContext *Context,
158 std::vector<StringRef> CheckedFunctions,
159 std::vector<StringRef> CheckedReturnTypes,
bool AllowCastToVoid)
161 CheckedFunctions(std::
move(CheckedFunctions)),
162 CheckedReturnTypes(std::
move(CheckedReturnTypes)),
163 AllowCastToVoid(AllowCastToVoid) {}
166 Options.store(Opts,
"CheckedFunctions",
168 Options.store(Opts,
"CheckedReturnTypes",
174 auto MatchedDirectCallExpr =
175 expr(callExpr(callee(functionDecl(
177 unless(isAssignmentOverloadedOperator()),
179 unless(returns(voidType())),
182 returns(hasCanonicalType(hasDeclaration(
184 CheckedReturnTypes)))))))))
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))));
194 auto UnusedInCompoundStmt =
195 compoundStmt(forEach(MatchedCallExpr),
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));
212 stmt(anyOf(UnusedInCompoundStmt, UnusedInIfStmt, UnusedInWhileStmt,
213 UnusedInDoStmt, UnusedInForStmt, UnusedInRangeForStmt,
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();
228 diag(Matched->getBeginLoc(),
229 "cast the expression to void to silence this warning",
230 DiagnosticIDs::Note);
UnusedReturnValueCheck(StringRef Name, ClangTidyContext *Context)
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID)
AST_MATCHER(BinaryOperator, isRelationalOperator)
inline ::clang::ast_matchers::internal::Matcher< NamedDecl > matchesAnyListedName(llvm::ArrayRef< StringRef > NameList)
std::string serializeStringList(ArrayRef< StringRef > Strings)
Serialize a sequence of names that can be parsed by parseStringList.
std::vector< StringRef > parseStringList(StringRef Option)
Parse a semicolon separated list of strings.
llvm::StringMap< ClangTidyValue > OptionMap