003 File Manager
Current Path:
/usr/src/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers
usr
/
src
/
contrib
/
llvm-project
/
clang
/
lib
/
StaticAnalyzer
/
Checkers
/
π
..
π
AllocationState.h
(1.41 KB)
π
AnalysisOrderChecker.cpp
(8.62 KB)
π
AnalyzerStatsChecker.cpp
(5.04 KB)
π
ArrayBoundChecker.cpp
(3.22 KB)
π
ArrayBoundCheckerV2.cpp
(13.07 KB)
π
BasicObjCFoundationChecks.cpp
(43.82 KB)
π
BlockInCriticalSectionChecker.cpp
(6.69 KB)
π
BoolAssignmentChecker.cpp
(3.45 KB)
π
BuiltinFunctionChecker.cpp
(5 KB)
π
CStringChecker.cpp
(93.24 KB)
π
CStringSyntaxChecker.cpp
(9.8 KB)
π
CXXSelfAssignmentChecker.cpp
(3.08 KB)
π
CallAndMessageChecker.cpp
(26.57 KB)
π
CastSizeChecker.cpp
(4.96 KB)
π
CastToStructChecker.cpp
(4.43 KB)
π
CastValueChecker.cpp
(19.65 KB)
π
CheckObjCDealloc.cpp
(37.83 KB)
π
CheckObjCInstMethSignature.cpp
(4.8 KB)
π
CheckPlacementNew.cpp
(11.91 KB)
π
CheckSecuritySyntaxOnly.cpp
(38.79 KB)
π
CheckSizeofPointer.cpp
(3.16 KB)
π
CheckerDocumentation.cpp
(14.64 KB)
π
ChrootChecker.cpp
(4.88 KB)
π
CloneChecker.cpp
(8.28 KB)
π
ContainerModeling.cpp
(39.85 KB)
π
ConversionChecker.cpp
(7.11 KB)
π
DeadStoresChecker.cpp
(17.82 KB)
π
DebugCheckers.cpp
(10.41 KB)
π
DebugContainerModeling.cpp
(4.94 KB)
π
DebugIteratorModeling.cpp
(5.15 KB)
π
DeleteWithNonVirtualDtorChecker.cpp
(5.35 KB)
π
DereferenceChecker.cpp
(10.54 KB)
π
DirectIvarAssignment.cpp
(8.02 KB)
π
DivZeroChecker.cpp
(3.42 KB)
π
DynamicTypeChecker.cpp
(7.31 KB)
π
DynamicTypePropagation.cpp
(42.11 KB)
π
EnumCastOutOfRangeChecker.cpp
(5.75 KB)
π
ExprInspectionChecker.cpp
(15.6 KB)
π
FixedAddressChecker.cpp
(2.33 KB)
π
FuchsiaHandleChecker.cpp
(23.1 KB)
π
GCDAntipatternChecker.cpp
(7.85 KB)
π
GTestChecker.cpp
(10.52 KB)
π
GenericTaintChecker.cpp
(34.31 KB)
π
IdenticalExprChecker.cpp
(18.88 KB)
π
InnerPointerChecker.cpp
(11.54 KB)
π
InterCheckerAPI.h
(1.09 KB)
π
InvalidatedIteratorChecker.cpp
(4.93 KB)
π
Iterator.cpp
(10.62 KB)
π
Iterator.h
(6.32 KB)
π
IteratorModeling.cpp
(31.33 KB)
π
IteratorRangeChecker.cpp
(12.64 KB)
π
IvarInvalidationChecker.cpp
(27.63 KB)
π
LLVMConventionsChecker.cpp
(9.9 KB)
π
LocalizationChecker.cpp
(52.38 KB)
π
MIGChecker.cpp
(11.3 KB)
π
MPI-Checker
π
MacOSKeychainAPIChecker.cpp
(25.21 KB)
π
MacOSXAPIChecker.cpp
(6.61 KB)
π
MallocChecker.cpp
(127.38 KB)
π
MallocOverflowSecurityChecker.cpp
(11.91 KB)
π
MallocSizeofChecker.cpp
(8.03 KB)
π
MismatchedIteratorChecker.cpp
(11.01 KB)
π
MmapWriteExecChecker.cpp
(3.22 KB)
π
Move.h
(1.07 KB)
π
MoveChecker.cpp
(27 KB)
π
NSAutoreleasePoolChecker.cpp
(2.93 KB)
π
NSErrorChecker.cpp
(10.6 KB)
π
NoReturnFunctionChecker.cpp
(5.48 KB)
π
NonNullParamChecker.cpp
(11.22 KB)
π
NonnullGlobalConstantsChecker.cpp
(5.09 KB)
π
NullabilityChecker.cpp
(46.95 KB)
π
NumberObjectConversionChecker.cpp
(13.69 KB)
π
OSObjectCStyleCast.cpp
(3.14 KB)
π
ObjCAtSyncChecker.cpp
(3.34 KB)
π
ObjCAutoreleaseWriteChecker.cpp
(8.62 KB)
π
ObjCContainersASTChecker.cpp
(5.5 KB)
π
ObjCContainersChecker.cpp
(6.71 KB)
π
ObjCMissingSuperCallChecker.cpp
(9.23 KB)
π
ObjCPropertyChecker.cpp
(3.03 KB)
π
ObjCSelfInitChecker.cpp
(16.21 KB)
π
ObjCSuperDeallocChecker.cpp
(9.33 KB)
π
ObjCUnusedIVarsChecker.cpp
(6.01 KB)
π
PaddingChecker.cpp
(14.26 KB)
π
PointerArithChecker.cpp
(12.18 KB)
π
PointerIterationChecker.cpp
(3.79 KB)
π
PointerSortingChecker.cpp
(4.5 KB)
π
PointerSubChecker.cpp
(2.56 KB)
π
PthreadLockChecker.cpp
(28.42 KB)
π
RetainCountChecker
π
ReturnPointerRangeChecker.cpp
(3.39 KB)
π
ReturnUndefChecker.cpp
(4.1 KB)
π
ReturnValueChecker.cpp
(5.79 KB)
π
RunLoopAutoreleaseLeakChecker.cpp
(7.2 KB)
π
STLAlgorithmModeling.cpp
(7 KB)
π
SimpleStreamChecker.cpp
(9.43 KB)
π
SmartPtr.h
(1.17 KB)
π
SmartPtrChecker.cpp
(2.68 KB)
π
SmartPtrModeling.cpp
(8.05 KB)
π
StackAddrEscapeChecker.cpp
(15 KB)
π
StdLibraryFunctionsChecker.cpp
(74.86 KB)
π
StreamChecker.cpp
(37.36 KB)
π
Taint.cpp
(9.04 KB)
π
Taint.h
(4.19 KB)
π
TaintTesterChecker.cpp
(2.17 KB)
π
TestAfterDivZeroChecker.cpp
(8.19 KB)
π
TraversalChecker.cpp
(4.38 KB)
π
TrustNonnullChecker.cpp
(9.12 KB)
π
UndefBranchChecker.cpp
(3.82 KB)
π
UndefCapturedBlockVarChecker.cpp
(3.64 KB)
π
UndefResultChecker.cpp
(7.19 KB)
π
UndefinedArraySubscriptChecker.cpp
(2.36 KB)
π
UndefinedAssignmentChecker.cpp
(3.74 KB)
π
UninitializedObject
π
UnixAPIChecker.cpp
(18.05 KB)
π
UnreachableCodeChecker.cpp
(9.59 KB)
π
VLASizeChecker.cpp
(10.95 KB)
π
ValistChecker.cpp
(15.65 KB)
π
VforkChecker.cpp
(7.67 KB)
π
VirtualCallChecker.cpp
(8.11 KB)
π
WebKit
π
Yaml.h
(2.06 KB)
π
cert
Editing: 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" using namespace clang; using namespace ento; using namespace ast_matchers; namespace { // ID of a node at which the diagnostic would be emitted. const char *WarnAtNode = "waitcall"; class GCDAntipatternChecker : public Checker<check::ASTCodeBody> { public: void checkASTCodeBody(const Decl *D, AnalysisManager &AM, BugReporter &BR) const; }; decltype(auto) callsName(const char *FunctionName) { return callee(functionDecl(hasName(FunctionName))); } decltype(auto) equalsBoundArgDecl(int ArgIdx, const char *DeclName) { return hasArgument(ArgIdx, ignoringParenCasts(declRefExpr( to(varDecl(equalsBoundNode(DeclName)))))); } decltype(auto) bindAssignmentToDecl(const char *DeclName) { return hasLHS(ignoringParenImpCasts( declRefExpr(to(varDecl().bind(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) { if (const auto* ND = dyn_cast<NamedDecl>(D)) { std::string DeclName = ND->getNameAsString(); if (StringRef(DeclName).startswith("test")) return true; } if (const auto *OD = dyn_cast<ObjCMethodDecl>(D)) { if (const auto *CD = dyn_cast<ObjCContainerDecl>(OD->getParent())) { std::string ContainerName = CD->getNameAsString(); StringRef CN(ContainerName); if (CN.contains_lower("test") || CN.contains_lower("mock")) return true; } } return false; } static auto findGCDAntiPatternWithSemaphore() -> decltype(compoundStmt()) { const char *SemaphoreBinding = "semaphore_name"; auto SemaphoreCreateM = callExpr(allOf( callsName("dispatch_semaphore_create"), hasArgument(0, ignoringParenCasts(integerLiteral(equals(0)))))); auto SemaphoreBindingM = anyOf( forEachDescendant( varDecl(hasDescendant(SemaphoreCreateM)).bind(SemaphoreBinding)), forEachDescendant(binaryOperator(bindAssignmentToDecl(SemaphoreBinding), hasRHS(SemaphoreCreateM)))); auto HasBlockArgumentM = hasAnyArgument(hasType( hasCanonicalType(blockPointerType()) )); auto ArgCallsSignalM = hasAnyArgument(stmt(hasDescendant(callExpr( allOf( callsName("dispatch_semaphore_signal"), equalsBoundArgDecl(0, SemaphoreBinding) ))))); auto HasBlockAndCallsSignalM = allOf(HasBlockArgumentM, ArgCallsSignalM); auto HasBlockCallingSignalM = forEachDescendant( stmt(anyOf( callExpr(HasBlockAndCallsSignalM), objcMessageExpr(HasBlockAndCallsSignalM) ))); auto SemaphoreWaitM = forEachDescendant( callExpr( allOf( callsName("dispatch_semaphore_wait"), equalsBoundArgDecl(0, SemaphoreBinding) ) ).bind(WarnAtNode)); return compoundStmt( SemaphoreBindingM, HasBlockCallingSignalM, SemaphoreWaitM); } static auto findGCDAntiPatternWithGroup() -> decltype(compoundStmt()) { const char *GroupBinding = "group_name"; auto DispatchGroupCreateM = callExpr(callsName("dispatch_group_create")); auto GroupBindingM = anyOf( forEachDescendant( varDecl(hasDescendant(DispatchGroupCreateM)).bind(GroupBinding)), forEachDescendant(binaryOperator(bindAssignmentToDecl(GroupBinding), hasRHS(DispatchGroupCreateM)))); auto GroupEnterM = forEachDescendant( stmt(callExpr(allOf(callsName("dispatch_group_enter"), equalsBoundArgDecl(0, GroupBinding))))); auto HasBlockArgumentM = hasAnyArgument(hasType( hasCanonicalType(blockPointerType()) )); auto ArgCallsSignalM = hasAnyArgument(stmt(hasDescendant(callExpr( allOf( callsName("dispatch_group_leave"), equalsBoundArgDecl(0, GroupBinding) ))))); auto HasBlockAndCallsLeaveM = allOf(HasBlockArgumentM, ArgCallsSignalM); auto AcceptsBlockM = forEachDescendant( stmt(anyOf( callExpr(HasBlockAndCallsLeaveM), objcMessageExpr(HasBlockAndCallsLeaveM) ))); auto GroupWaitM = forEachDescendant( callExpr( allOf( callsName("dispatch_group_wait"), equalsBoundArgDecl(0, GroupBinding) ) ).bind(WarnAtNode)); return compoundStmt(GroupBindingM, GroupEnterM, AcceptsBlockM, GroupWaitM); } static void emitDiagnostics(const BoundNodes &Nodes, const char* Type, BugReporter &BR, AnalysisDeclContext *ADC, const GCDAntipatternChecker *Checker) { const auto *SW = Nodes.getNodeAs<CallExpr>(WarnAtNode); assert(SW); std::string Diagnostics; llvm::raw_string_ostream OS(Diagnostics); OS << "Waiting on a callback using a " << Type << " creates useless threads " << "and is subject to priority inversion; consider " << "using a synchronous API or changing the caller to be asynchronous"; BR.EmitBasicReport( ADC->getDecl(), Checker, /*Name=*/"GCD performance anti-pattern", /*BugCategory=*/"Performance", OS.str(), PathDiagnosticLocation::createBegin(SW, BR.getSourceManager(), ADC), SW->getSourceRange()); } void GCDAntipatternChecker::checkASTCodeBody(const Decl *D, AnalysisManager &AM, BugReporter &BR) const { if (isTest(D)) return; AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D); auto SemaphoreMatcherM = findGCDAntiPatternWithSemaphore(); auto Matches = match(SemaphoreMatcherM, *D->getBody(), AM.getASTContext()); for (BoundNodes Match : Matches) emitDiagnostics(Match, "semaphore", BR, ADC, this); auto GroupMatcherM = findGCDAntiPatternWithGroup(); Matches = match(GroupMatcherM, *D->getBody(), AM.getASTContext()); for (BoundNodes Match : Matches) emitDiagnostics(Match, "group", BR, ADC, this); } } // end of anonymous namespace void ento::registerGCDAntipattern(CheckerManager &Mgr) { Mgr.registerChecker<GCDAntipatternChecker>(); } bool ento::shouldRegisterGCDAntipattern(const CheckerManager &mgr) { return true; }
Upload File
Create Folder