llvm/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp

//===- GCDAntipatternChecker.cpp ---------------------------------*- C++ -*-==//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines GCDAntipatternChecker which checks against a common
// antipattern when synchronous API is emulated from asynchronous callbacks
// using a semaphore:
//
//   dispatch_semaphore_t sema = dispatch_semaphore_create(0);
//
//   AnyCFunctionCall(^{
//     // code…
//     dispatch_semaphore_signal(sema);
//   })
//   dispatch_semaphore_wait(sema, *)
//
// Such code is a common performance problem, due to inability of GCD to
// properly handle QoS when a combination of queues and semaphores is used.
// Good code would either use asynchronous API (when available), or perform
// the necessary action in asynchronous callback.
//
// Currently, the check is performed using a simple heuristical AST pattern
// matching.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "llvm/Support/Debug.h"

usingnamespaceclang;
usingnamespaceento;
usingnamespaceast_matchers;

namespace {

// ID of a node at which the diagnostic would be emitted.
const char *WarnAtNode =;

class GCDAntipatternChecker : public Checker<check::ASTCodeBody> {};

decltype(auto) callsName(const char *FunctionName) {}

decltype(auto) equalsBoundArgDecl(int ArgIdx, const char *DeclName) {}

decltype(auto) bindAssignmentToDecl(const char *DeclName) {}

/// The pattern is very common in tests, and it is OK to use it there.
/// We have to heuristics for detecting tests: method name starts with "test"
/// (used in XCTest), and a class name contains "mock" or "test" (used in
/// helpers which are not tests themselves, but used exclusively in tests).
static bool isTest(const Decl *D) {}

static auto findGCDAntiPatternWithSemaphore() -> decltype(compoundStmt()) {}

static auto findGCDAntiPatternWithGroup() -> decltype(compoundStmt()) {}

static void emitDiagnostics(const BoundNodes &Nodes,
                            const char* Type,
                            BugReporter &BR,
                            AnalysisDeclContext *ADC,
                            const GCDAntipatternChecker *Checker) {}

void GCDAntipatternChecker::checkASTCodeBody(const Decl *D,
                                             AnalysisManager &AM,
                                             BugReporter &BR) const {}

} // end of anonymous namespace

void ento::registerGCDAntipattern(CheckerManager &Mgr) {}

bool ento::shouldRegisterGCDAntipattern(const CheckerManager &mgr) {}