18 auto HasUniqueLock = hasDescendant(declRefExpr(
19 hasDeclaration(varDecl(hasType(recordDecl(classTemplateSpecializationDecl(
20 hasName(
"::std::unique_lock"),
22 0, templateArgument(refersToType(qualType(hasDeclaration(
23 cxxRecordDecl(hasName(
"::std::mutex"))))))))))))));
25 auto HasWaitDescendantCpp = hasDescendant(
27 anyOf(allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
28 hasName(
"::std::condition_variable::wait"),
29 parameterCountIs(1))))),
30 onImplicitObjectArgument(
31 declRefExpr(to(varDecl(hasType(references(recordDecl(
32 hasName(
"::std::condition_variable")))))))),
34 allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
35 hasName(
"::std::condition_variable::wait_for"),
36 parameterCountIs(2))))),
37 onImplicitObjectArgument(
38 declRefExpr(to(varDecl(hasType(references(recordDecl(
39 hasName(
"::std::condition_variable")))))))),
41 allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
42 hasName(
"::std::condition_variable::wait_until"),
43 parameterCountIs(2))))),
44 onImplicitObjectArgument(
45 declRefExpr(to(varDecl(hasType(references(recordDecl(
46 hasName(
"::std::condition_variable")))))))),
50 auto HasWaitDescendantC = hasDescendant(
51 callExpr(callee(functionDecl(hasAnyName(
"cnd_wait",
"cnd_timedwait"))))
53 if (getLangOpts().CPlusPlus) {
56 ifStmt(HasWaitDescendantCpp,
57 unless(hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt)
58 .with(HasWaitDescendantCpp)))),
63 ifStmt(HasWaitDescendantC,
65 hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt)
66 .with(HasWaitDescendantC)),
67 hasParent(mapAnyOf(whileStmt, forStmt, doStmt)),
68 hasParent(compoundStmt(
69 hasParent(mapAnyOf(whileStmt, forStmt, doStmt))))))),
75 const MatchFinder::MatchResult &Result) {
76 const auto *MatchedWait = Result.Nodes.getNodeAs<CallExpr>(
"wait");
77 const StringRef WaitName = MatchedWait->getDirectCallee()->getName();
78 diag(MatchedWait->getExprLoc(),
79 "'%0' should be placed inside a while statement %select{|or used with a "
80 "conditional parameter}1")
81 << WaitName << (WaitName !=
"cnd_wait" && WaitName !=
"cnd_timedwait");