123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- //===--- SpuriouslyWakeUpFunctionsCheck.cpp - clang-tidy ------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "SpuriouslyWakeUpFunctionsCheck.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/ASTMatchers/ASTMatchFinder.h"
- using namespace clang::ast_matchers;
- namespace clang::tidy::bugprone {
- void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) {
- auto HasUniqueLock = hasDescendant(declRefExpr(
- hasDeclaration(varDecl(hasType(recordDecl(classTemplateSpecializationDecl(
- hasName("::std::unique_lock"),
- hasTemplateArgument(
- 0, templateArgument(refersToType(qualType(hasDeclaration(
- cxxRecordDecl(hasName("::std::mutex"))))))))))))));
- auto HasWaitDescendantCpp = hasDescendant(
- cxxMemberCallExpr(
- anyOf(
- allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
- allOf(hasName("::std::condition_variable::wait"),
- parameterCountIs(1)))))),
- onImplicitObjectArgument(
- declRefExpr(to(varDecl(hasType(references(recordDecl(
- hasName("::std::condition_variable")))))))),
- HasUniqueLock),
- allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
- allOf(hasName("::std::condition_variable::wait_for"),
- parameterCountIs(2)))))),
- onImplicitObjectArgument(
- declRefExpr(to(varDecl(hasType(references(recordDecl(
- hasName("::std::condition_variable")))))))),
- HasUniqueLock),
- allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl(
- allOf(hasName("::std::condition_variable::wait_until"),
- parameterCountIs(2)))))),
- onImplicitObjectArgument(
- declRefExpr(to(varDecl(hasType(references(recordDecl(
- hasName("::std::condition_variable")))))))),
- HasUniqueLock)
- ))
- .bind("wait"));
- auto HasWaitDescendantC = hasDescendant(
- callExpr(callee(functionDecl(hasAnyName("cnd_wait", "cnd_timedwait"))))
- .bind("wait"));
- if (getLangOpts().CPlusPlus) {
- // Check for `CON54-CPP`
- Finder->addMatcher(
- ifStmt(HasWaitDescendantCpp,
- unless(hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt)
- .with(HasWaitDescendantCpp)))),
- this);
- } else {
- // Check for `CON36-C`
- Finder->addMatcher(
- ifStmt(HasWaitDescendantC,
- unless(anyOf(
- hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt)
- .with(HasWaitDescendantC)),
- hasParent(mapAnyOf(whileStmt, forStmt, doStmt)),
- hasParent(compoundStmt(
- hasParent(mapAnyOf(whileStmt, forStmt, doStmt))))))),
- this);
- }
- }
- void SpuriouslyWakeUpFunctionsCheck::check(
- const MatchFinder::MatchResult &Result) {
- const auto *MatchedWait = Result.Nodes.getNodeAs<CallExpr>("wait");
- StringRef WaitName = MatchedWait->getDirectCallee()->getName();
- diag(MatchedWait->getExprLoc(),
- "'%0' should be placed inside a while statement %select{|or used with a "
- "conditional parameter}1")
- << WaitName << (WaitName != "cnd_wait" && WaitName != "cnd_timedwait");
- }
- } // namespace clang::tidy::bugprone
|