10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
19 void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) {
21 auto hasUniqueLock = hasDescendant(declRefExpr(
22 hasDeclaration(varDecl(hasType(recordDecl(classTemplateSpecializationDecl(
23 hasName(
"::std::unique_lock"),
25 0, templateArgument(refersToType(qualType(hasDeclaration(
26 cxxRecordDecl(hasName(
"::std::mutex"))))))))))))));
28 auto hasWaitDescendantCPP = hasDescendant(
31 allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
32 allOf(hasName(
"::std::condition_variable::wait"),
33 parameterCountIs(1)))))),
34 onImplicitObjectArgument(
35 declRefExpr(to(varDecl(hasType(references(recordDecl(
36 hasName(
"::std::condition_variable")))))))),
38 allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
39 allOf(hasName(
"::std::condition_variable::wait_for"),
40 parameterCountIs(2)))))),
41 onImplicitObjectArgument(
42 declRefExpr(to(varDecl(hasType(references(recordDecl(
43 hasName(
"::std::condition_variable")))))))),
45 allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
46 allOf(hasName(
"::std::condition_variable::wait_until"),
47 parameterCountIs(2)))))),
48 onImplicitObjectArgument(
49 declRefExpr(to(varDecl(hasType(references(recordDecl(
50 hasName(
"::std::condition_variable")))))))),
56 auto hasWaitDescendantC = hasDescendant(
57 callExpr(callee(functionDecl(hasAnyName(
"cnd_wait",
"cnd_timedwait"))))
59 if (getLangOpts().CPlusPlus) {
64 allOf(hasWaitDescendantCPP,
65 unless(anyOf(hasDescendant(ifStmt(hasWaitDescendantCPP)),
66 hasDescendant(whileStmt(hasWaitDescendantCPP)),
67 hasDescendant(forStmt(hasWaitDescendantCPP)),
68 hasDescendant(doStmt(hasWaitDescendantCPP)))))
77 allOf(hasWaitDescendantC,
78 unless(anyOf(hasDescendant(ifStmt(hasWaitDescendantC)),
79 hasDescendant(whileStmt(hasWaitDescendantC)),
80 hasDescendant(forStmt(hasWaitDescendantC)),
81 hasDescendant(doStmt(hasWaitDescendantC)),
82 hasParent(whileStmt()),
83 hasParent(compoundStmt(hasParent(whileStmt()))),
85 hasParent(compoundStmt(hasParent(forStmt()))),
87 hasParent(compoundStmt(hasParent(doStmt())))))
96 void SpuriouslyWakeUpFunctionsCheck::check(
97 const MatchFinder::MatchResult &Result) {
98 const auto *MatchedWait = Result.Nodes.getNodeAs<CallExpr>(
"wait");
99 StringRef WaitName = MatchedWait->getDirectCallee()->getName();
100 diag(MatchedWait->getExprLoc(),
101 "'%0' should be placed inside a while statement %select{|or used with a "
102 "conditional parameter}1")
103 << WaitName << (WaitName !=
"cnd_wait" && WaitName !=
"cnd_timedwait");