clang-tools  14.0.0git
SpuriouslyWakeUpFunctionsCheck.cpp
Go to the documentation of this file.
1 //===--- SpuriouslyWakeUpFunctionsCheck.cpp - clang-tidy ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 
13 using namespace clang::ast_matchers;
14 
15 namespace clang {
16 namespace tidy {
17 namespace bugprone {
18 
19 void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) {
20 
21  auto HasUniqueLock = hasDescendant(declRefExpr(
22  hasDeclaration(varDecl(hasType(recordDecl(classTemplateSpecializationDecl(
23  hasName("::std::unique_lock"),
24  hasTemplateArgument(
25  0, templateArgument(refersToType(qualType(hasDeclaration(
26  cxxRecordDecl(hasName("::std::mutex"))))))))))))));
27 
28  auto HasWaitDescendantCpp = hasDescendant(
29  cxxMemberCallExpr(
30  anyOf(
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")))))))),
37  HasUniqueLock),
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")))))))),
44  HasUniqueLock),
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")))))))),
51  HasUniqueLock)
52 
53  ))
54  .bind("wait"));
55 
56  auto HasWaitDescendantC = hasDescendant(
57  callExpr(callee(functionDecl(hasAnyName("cnd_wait", "cnd_timedwait"))))
58  .bind("wait"));
59  if (getLangOpts().CPlusPlus) {
60  // Check for `CON54-CPP`
61  Finder->addMatcher(
62  ifStmt(HasWaitDescendantCpp,
63  unless(hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt)
64  .with(HasWaitDescendantCpp)))),
65  this);
66  } else {
67  // Check for `CON36-C`
68  Finder->addMatcher(
69  ifStmt(HasWaitDescendantC,
70  unless(anyOf(
71  hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt)
72  .with(HasWaitDescendantC)),
73  hasParent(mapAnyOf(whileStmt, forStmt, doStmt)),
74  hasParent(compoundStmt(
75  hasParent(mapAnyOf(whileStmt, forStmt, doStmt))))))),
76  this);
77  }
78 }
79 
81  const MatchFinder::MatchResult &Result) {
82  const auto *MatchedWait = Result.Nodes.getNodeAs<CallExpr>("wait");
83  StringRef WaitName = MatchedWait->getDirectCallee()->getName();
84  diag(MatchedWait->getExprLoc(),
85  "'%0' should be placed inside a while statement %select{|or used with a "
86  "conditional parameter}1")
87  << WaitName << (WaitName != "cnd_wait" && WaitName != "cnd_timedwait");
88 }
89 } // namespace bugprone
90 } // namespace tidy
91 } // namespace clang
clang::ast_matchers
Definition: AbseilMatcher.h:14
clang::clangd::check
bool check(llvm::StringRef File, llvm::function_ref< bool(const Position &)> ShouldCheckLine, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, bool EnableCodeCompletion)
Definition: Check.cpp:259
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
SpuriouslyWakeUpFunctionsCheck.h