brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.7 KiB · fd82b1c Raw
84 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "SpuriouslyWakeUpFunctionsCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::bugprone {16 17void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) {18  auto HasUniqueLock = hasDescendant(declRefExpr(19      hasDeclaration(varDecl(hasType(recordDecl(classTemplateSpecializationDecl(20          hasName("::std::unique_lock"),21          hasTemplateArgument(22              0, templateArgument(refersToType(qualType(hasDeclaration(23                     cxxRecordDecl(hasName("::std::mutex"))))))))))))));24 25  auto HasWaitDescendantCpp = hasDescendant(26      cxxMemberCallExpr(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")))))))),33                      HasUniqueLock),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")))))))),40                      HasUniqueLock),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")))))))),47                      HasUniqueLock)))48          .bind("wait"));49 50  auto HasWaitDescendantC = hasDescendant(51      callExpr(callee(functionDecl(hasAnyName("cnd_wait", "cnd_timedwait"))))52          .bind("wait"));53  if (getLangOpts().CPlusPlus) {54    // Check for `CON54-CPP`55    Finder->addMatcher(56        ifStmt(HasWaitDescendantCpp,57               unless(hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt)58                                        .with(HasWaitDescendantCpp)))),59        this);60  } else {61    // Check for `CON36-C`62    Finder->addMatcher(63        ifStmt(HasWaitDescendantC,64               unless(anyOf(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))))))),70        this);71  }72}73 74void SpuriouslyWakeUpFunctionsCheck::check(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");82}83} // namespace clang::tidy::bugprone84