10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
19 auto HasUniqueLock = hasDescendant(declRefExpr(
20 hasDeclaration(varDecl(hasType(recordDecl(classTemplateSpecializationDecl(
21 hasName(
"::std::unique_lock"),
23 0, templateArgument(refersToType(qualType(hasDeclaration(
24 cxxRecordDecl(hasName(
"::std::mutex"))))))))))))));
26 auto HasWaitDescendantCpp = hasDescendant(
28 anyOf(allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
29 hasName(
"::std::condition_variable::wait"),
30 parameterCountIs(1))))),
31 onImplicitObjectArgument(
32 declRefExpr(to(varDecl(hasType(references(recordDecl(
33 hasName(
"::std::condition_variable")))))))),
35 allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
36 hasName(
"::std::condition_variable::wait_for"),
37 parameterCountIs(2))))),
38 onImplicitObjectArgument(
39 declRefExpr(to(varDecl(hasType(references(recordDecl(
40 hasName(
"::std::condition_variable")))))))),
42 allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
43 hasName(
"::std::condition_variable::wait_until"),
44 parameterCountIs(2))))),
45 onImplicitObjectArgument(
46 declRefExpr(to(varDecl(hasType(references(recordDecl(
47 hasName(
"::std::condition_variable")))))))),
53 auto HasWaitDescendantC = hasDescendant(
54 callExpr(callee(functionDecl(hasAnyName(
"cnd_wait",
"cnd_timedwait"))))
59 ifStmt(HasWaitDescendantCpp,
60 unless(hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt)
61 .with(HasWaitDescendantCpp)))),
66 ifStmt(HasWaitDescendantC,
68 hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt)
69 .with(HasWaitDescendantC)),
70 hasParent(mapAnyOf(whileStmt, forStmt, doStmt)),
71 hasParent(compoundStmt(
72 hasParent(mapAnyOf(whileStmt, forStmt, doStmt))))))),
78 const MatchFinder::MatchResult &Result) {
79 const auto *MatchedWait = Result.Nodes.getNodeAs<CallExpr>(
"wait");
80 StringRef WaitName = MatchedWait->getDirectCallee()->getName();
81 diag(MatchedWait->getExprLoc(),
82 "'%0' should be placed inside a while statement %select{|or used with a "
83 "conditional parameter}1")
84 << WaitName << (WaitName !=
"cnd_wait" && WaitName !=
"cnd_timedwait");
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
const LangOptions & getLangOpts() const
Returns the language options from the context.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.