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 FunctionDecl *InstantiatedFrom = Node.getInstantiatedFromMemberFunction();
29 return InnerMatcher.matches(InstantiatedFrom ? *InstantiatedFrom : Node,
33constexpr std::initializer_list<OverloadedOperatorKind>
34 AssignmentOverloadedOperatorKinds = {
35 OO_Equal, OO_PlusEqual, OO_MinusEqual, OO_StarEqual,
36 OO_SlashEqual, OO_PercentEqual, OO_CaretEqual, OO_AmpEqual,
37 OO_PipeEqual, OO_LessLessEqual, OO_GreaterGreaterEqual, OO_PlusPlus,
40AST_MATCHER(FunctionDecl, isAssignmentOverloadedOperator) {
41 return llvm::is_contained(AssignmentOverloadedOperatorKinds,
42 Node.getOverloadedOperator());
47 ClangTidyContext *Context)
48 : ClangTidyCheck(Name, Context),
50 Options.get(
"CheckedFunctions",
"^::std::async$;"
55 "^::std::unique_ptr::release$;"
56 "^::std::basic_string::empty$;"
57 "^::std::vector::empty$;"
58 "^::std::back_inserter$;"
63 "^::std::lower_bound$;"
65 "^::std::map::count$;"
67 "^::std::map::lower_bound$;"
68 "^::std::multimap::equal_range$;"
69 "^::std::multimap::upper_bound$;"
70 "^::std::set::count$;"
73 "^::std::setprecision$;"
75 "^::std::upper_bound$;"
76 "^::std::vector::at$;"
126 "^::pthread_getspecific$;"
127 "^::pthread_mutex_trylock$;"
142 Options.get(
"CheckedReturnTypes",
"^::std::error_code$;"
143 "^::std::error_condition$;"
146 "^::boost::system::error_code$"))),
147 AllowCastToVoid(Options.get(
"AllowCastToVoid", false)) {}
149UnusedReturnValueCheck::UnusedReturnValueCheck(
150 llvm::StringRef Name, ClangTidyContext *Context,
151 std::vector<StringRef> CheckedFunctions)
152 : UnusedReturnValueCheck(Name, Context, std::
move(CheckedFunctions), {},
155UnusedReturnValueCheck::UnusedReturnValueCheck(
156 llvm::StringRef Name, ClangTidyContext *Context,
157 std::vector<StringRef> CheckedFunctions,
158 std::vector<StringRef> CheckedReturnTypes,
bool AllowCastToVoid)
160 CheckedFunctions(std::
move(CheckedFunctions)),
161 CheckedReturnTypes(std::
move(CheckedReturnTypes)),
162 AllowCastToVoid(AllowCastToVoid) {}
165 Options.store(Opts,
"CheckedFunctions",
167 Options.store(Opts,
"CheckedReturnTypes",
173 auto MatchedDirectCallExpr =
174 expr(callExpr(callee(functionDecl(
176 unless(isAssignmentOverloadedOperator()),
178 unless(returns(voidType())),
181 returns(hasCanonicalType(hasDeclaration(
183 CheckedReturnTypes)))))))))
186 auto CheckCastToVoid =
187 AllowCastToVoid ? castExpr(unless(hasCastKind(CK_ToVoid))) : castExpr();
188 auto MatchedCallExpr = expr(
189 anyOf(MatchedDirectCallExpr,
190 explicitCastExpr(unless(cxxFunctionalCastExpr()), CheckCastToVoid,
191 hasSourceExpression(MatchedDirectCallExpr))));
193 auto UnusedInCompoundStmt =
194 compoundStmt(forEach(MatchedCallExpr),
199 unless(hasParent(stmtExpr())));
200 auto UnusedInIfStmt =
201 ifStmt(eachOf(hasThen(MatchedCallExpr), hasElse(MatchedCallExpr)));
202 auto UnusedInWhileStmt = whileStmt(hasBody(MatchedCallExpr));
203 auto UnusedInDoStmt = doStmt(hasBody(MatchedCallExpr));
204 auto UnusedInForStmt =
205 forStmt(eachOf(hasLoopInit(MatchedCallExpr),
206 hasIncrement(MatchedCallExpr), hasBody(MatchedCallExpr)));
207 auto UnusedInRangeForStmt = cxxForRangeStmt(hasBody(MatchedCallExpr));
208 auto UnusedInCaseStmt = switchCase(forEach(MatchedCallExpr));
211 stmt(anyOf(UnusedInCompoundStmt, UnusedInIfStmt, UnusedInWhileStmt,
212 UnusedInDoStmt, UnusedInForStmt, UnusedInRangeForStmt,
218 if (
const auto *Matched = Result.Nodes.getNodeAs<CallExpr>(
"match")) {
219 diag(Matched->getBeginLoc(),
220 "the value returned by this function should not be disregarded; "
221 "neglecting it may lead to errors")
222 << Matched->getSourceRange();
227 diag(Matched->getBeginLoc(),
228 "cast the expression to void to silence this warning",
229 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