Author: george.karpenkov Date: Mon Mar 12 11:27:36 2018 New Revision: 327309
URL: http://llvm.org/viewvc/llvm-project?rev=327309&view=rev Log: [analyzer] Move the GCDAsyncSemaphoreChecker to optin.performance rdar://38383753 Differential Revision: https://reviews.llvm.org/D44228 Added: cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp - copied, changed from r327294, cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp cfe/trunk/test/Analysis/gcdantipatternchecker_test.m - copied, changed from r327294, cfe/trunk/test/Analysis/gcdasyncsemaphorechecker_test.m Removed: cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp cfe/trunk/test/Analysis/gcdasyncsemaphorechecker_test.m Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=327309&r1=327308&r2=327309&view=diff ============================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Mon Mar 12 11:27:36 2018 @@ -610,12 +610,12 @@ def ObjCSuperDeallocChecker : Checker<"S } // end "osx.cocoa" -let ParentPackage = OSXAlpha in { +let ParentPackage = Performance in { -def GCDAsyncSemaphoreChecker : Checker<"GCDAsyncSemaphore">, - HelpText<"Checker for performance anti-pattern when using semaphors from async API">, - DescFile<"GCDAsyncSemaphoreChecker.cpp">; -} // end "alpha.osx" +def GCDAntipattern : Checker<"GCDAntipattern">, + HelpText<"Check for performance anti-patterns when using Grand Central Dispatch">, + DescFile<"GCDAntipatternChecker.cpp">; +} // end "optin.performance" let ParentPackage = CocoaAlpha in { Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=327309&r1=327308&r2=327309&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Mon Mar 12 11:27:36 2018 @@ -37,7 +37,7 @@ add_clang_library(clangStaticAnalyzerChe DynamicTypeChecker.cpp ExprInspectionChecker.cpp FixedAddressChecker.cpp - GCDAsyncSemaphoreChecker.cpp + GCDAntipatternChecker.cpp GenericTaintChecker.cpp GTestChecker.cpp IdenticalExprChecker.cpp Copied: cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp (from r327294, cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp) URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp?p2=cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp&p1=cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp&r1=327294&r2=327309&rev=327309&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp Mon Mar 12 11:27:36 2018 @@ -1,4 +1,4 @@ -//===- GCDAsyncSemaphoreChecker.cpp -----------------------------*- C++ -*-==// +//===- GCDAntipatternChecker.cpp ---------------------------------*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -7,20 +7,20 @@ // //===----------------------------------------------------------------------===// // -// This file defines GCDAsyncSemaphoreChecker which checks against a common +// This file defines GCDAntipatternChecker which checks against a common // antipattern when synchronous API is emulated from asynchronous callbacks -// using a semaphor: +// using a semaphore: +// +// dispatch_semaphore_t sema = dispatch_semaphore_create(0); // -// dispatch_semapshore_t sema = dispatch_semaphore_create(0); - // AnyCFunctionCall(^{ // // code⦠-// dispatch_semapshore_signal(sema); +// dispatch_semaphore_signal(sema); // }) -// dispatch_semapshore_wait(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 semaphors is used. +// 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. // @@ -37,8 +37,6 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "llvm/Support/Debug.h" -#define DEBUG_TYPE "gcdasyncsemaphorechecker" - using namespace clang; using namespace ento; using namespace ast_matchers; @@ -47,7 +45,7 @@ namespace { const char *WarningBinding = "semaphore_wait"; -class GCDAsyncSemaphoreChecker : public Checker<check::ASTCodeBody> { +class GCDAntipatternChecker : public Checker<check::ASTCodeBody> { public: void checkASTCodeBody(const Decl *D, AnalysisManager &AM, @@ -56,13 +54,13 @@ public: class Callback : public MatchFinder::MatchCallback { BugReporter &BR; - const GCDAsyncSemaphoreChecker *C; + const GCDAntipatternChecker *C; AnalysisDeclContext *ADC; public: Callback(BugReporter &BR, AnalysisDeclContext *ADC, - const GCDAsyncSemaphoreChecker *C) : BR(BR), C(C), ADC(ADC) {} + const GCDAntipatternChecker *C) : BR(BR), C(C), ADC(ADC) {} virtual void run(const MatchFinder::MatchResult &Result) override; }; @@ -83,7 +81,7 @@ auto bindAssignmentToDecl(const char *De declRefExpr(to(varDecl().bind(DeclName))))); } -void GCDAsyncSemaphoreChecker::checkASTCodeBody(const Decl *D, +void GCDAntipatternChecker::checkASTCodeBody(const Decl *D, AnalysisManager &AM, BugReporter &BR) const { @@ -93,6 +91,14 @@ void GCDAsyncSemaphoreChecker::checkASTC if (StringRef(DeclName).startswith("test")) return; } + 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; + } + } const char *SemaphoreBinding = "semaphore_name"; auto SemaphoreCreateM = callExpr(callsName("dispatch_semaphore_create")); @@ -146,14 +152,15 @@ void Callback::run(const MatchFinder::Ma ADC->getDecl(), C, /*Name=*/"Semaphore performance anti-pattern", /*Category=*/"Performance", - "Possible semaphore performance anti-pattern: wait on a semaphore " - "signalled to in a callback", + "Waiting on a semaphore with Grand Central Dispatch creates useless " + "threads and is subject to priority inversion; consider " + "using a synchronous API or changing the caller to be asynchronous", PathDiagnosticLocation::createBegin(SW, BR.getSourceManager(), ADC), SW->getSourceRange()); } } -void ento::registerGCDAsyncSemaphoreChecker(CheckerManager &Mgr) { - Mgr.registerChecker<GCDAsyncSemaphoreChecker>(); +void ento::registerGCDAntipattern(CheckerManager &Mgr) { + Mgr.registerChecker<GCDAntipatternChecker>(); } Removed: cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp?rev=327308&view=auto ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp (removed) @@ -1,159 +0,0 @@ -//===- GCDAsyncSemaphoreChecker.cpp -----------------------------*- C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines GCDAsyncSemaphoreChecker which checks against a common -// antipattern when synchronous API is emulated from asynchronous callbacks -// using a semaphor: -// -// dispatch_semapshore_t sema = dispatch_semaphore_create(0); - -// AnyCFunctionCall(^{ -// // code⦠-// dispatch_semapshore_signal(sema); -// }) -// dispatch_semapshore_wait(sema, *) -// -// Such code is a common performance problem, due to inability of GCD to -// properly handle QoS when a combination of queues and semaphors 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 "ClangSACheckers.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" - -#define DEBUG_TYPE "gcdasyncsemaphorechecker" - -using namespace clang; -using namespace ento; -using namespace ast_matchers; - -namespace { - -const char *WarningBinding = "semaphore_wait"; - -class GCDAsyncSemaphoreChecker : public Checker<check::ASTCodeBody> { -public: - void checkASTCodeBody(const Decl *D, - AnalysisManager &AM, - BugReporter &BR) const; -}; - -class Callback : public MatchFinder::MatchCallback { - BugReporter &BR; - const GCDAsyncSemaphoreChecker *C; - AnalysisDeclContext *ADC; - -public: - Callback(BugReporter &BR, - AnalysisDeclContext *ADC, - const GCDAsyncSemaphoreChecker *C) : BR(BR), C(C), ADC(ADC) {} - - virtual void run(const MatchFinder::MatchResult &Result) override; -}; - -auto callsName(const char *FunctionName) - -> decltype(callee(functionDecl())) { - return callee(functionDecl(hasName(FunctionName))); -} - -auto equalsBoundArgDecl(int ArgIdx, const char *DeclName) - -> decltype(hasArgument(0, expr())) { - return hasArgument(ArgIdx, ignoringParenCasts(declRefExpr( - to(varDecl(equalsBoundNode(DeclName)))))); -} - -auto bindAssignmentToDecl(const char *DeclName) -> decltype(hasLHS(expr())) { - return hasLHS(ignoringParenImpCasts( - declRefExpr(to(varDecl().bind(DeclName))))); -} - -void GCDAsyncSemaphoreChecker::checkASTCodeBody(const Decl *D, - AnalysisManager &AM, - BugReporter &BR) const { - - // The pattern is very common in tests, and it is OK to use it there. - if (const auto* ND = dyn_cast<NamedDecl>(D)) { - std::string DeclName = ND->getNameAsString(); - if (StringRef(DeclName).startswith("test")) - return; - } - - const char *SemaphoreBinding = "semaphore_name"; - auto SemaphoreCreateM = callExpr(callsName("dispatch_semaphore_create")); - - auto SemaphoreBindingM = anyOf( - forEachDescendant( - varDecl(hasDescendant(SemaphoreCreateM)).bind(SemaphoreBinding)), - forEachDescendant(binaryOperator(bindAssignmentToDecl(SemaphoreBinding), - hasRHS(SemaphoreCreateM)))); - - auto SemaphoreWaitM = forEachDescendant( - callExpr( - allOf( - callsName("dispatch_semaphore_wait"), - equalsBoundArgDecl(0, SemaphoreBinding) - ) - ).bind(WarningBinding)); - - auto HasBlockArgumentM = hasAnyArgument(hasType( - hasCanonicalType(blockPointerType()) - )); - - auto ArgCallsSignalM = hasArgument(0, hasDescendant(callExpr( - allOf( - callsName("dispatch_semaphore_signal"), - equalsBoundArgDecl(0, SemaphoreBinding) - )))); - - auto HasBlockAndCallsSignalM = allOf(HasBlockArgumentM, ArgCallsSignalM); - - auto AcceptsBlockM = - forEachDescendant( - stmt(anyOf( - callExpr(HasBlockAndCallsSignalM), - objcMessageExpr(HasBlockAndCallsSignalM) - ))); - - auto FinalM = compoundStmt(SemaphoreBindingM, SemaphoreWaitM, AcceptsBlockM); - - MatchFinder F; - Callback CB(BR, AM.getAnalysisDeclContext(D), this); - - F.addMatcher(FinalM, &CB); - F.match(*D->getBody(), AM.getASTContext()); -} - -void Callback::run(const MatchFinder::MatchResult &Result) { - const auto *SW = Result.Nodes.getNodeAs<CallExpr>(WarningBinding); - assert(SW); - BR.EmitBasicReport( - ADC->getDecl(), C, - /*Name=*/"Semaphore performance anti-pattern", - /*Category=*/"Performance", - "Possible semaphore performance anti-pattern: wait on a semaphore " - "signalled to in a callback", - PathDiagnosticLocation::createBegin(SW, BR.getSourceManager(), ADC), - SW->getSourceRange()); -} - -} - -void ento::registerGCDAsyncSemaphoreChecker(CheckerManager &Mgr) { - Mgr.registerChecker<GCDAsyncSemaphoreChecker>(); -} Copied: cfe/trunk/test/Analysis/gcdantipatternchecker_test.m (from r327294, cfe/trunk/test/Analysis/gcdasyncsemaphorechecker_test.m) URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/gcdantipatternchecker_test.m?p2=cfe/trunk/test/Analysis/gcdantipatternchecker_test.m&p1=cfe/trunk/test/Analysis/gcdasyncsemaphorechecker_test.m&r1=327294&r2=327309&rev=327309&view=diff ============================================================================== --- cfe/trunk/test/Analysis/gcdasyncsemaphorechecker_test.m (original) +++ cfe/trunk/test/Analysis/gcdantipatternchecker_test.m Mon Mar 12 11:27:36 2018 @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.osx.GCDAsyncSemaphore %s -fblocks -verify +// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.performance.GCDAntipattern %s -fblocks -verify typedef signed char BOOL; @protocol NSObject - (BOOL)isEqual:(id)object; @end @interface NSObject <NSObject> {} @@ -27,7 +27,7 @@ void use_semaphor_antipattern() { func(^{ dispatch_semaphore_signal(sema); }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } // It's OK to use pattern in tests. @@ -47,14 +47,14 @@ void use_semaphor_antipattern_multiple_t func(^{ dispatch_semaphore_signal(sema1); }); - dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} dispatch_semaphore_t sema2 = dispatch_semaphore_create(0); func(^{ dispatch_semaphore_signal(sema2); }); - dispatch_semaphore_wait(sema2, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema2, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } void use_semaphor_antipattern_multiple_wait() { @@ -64,8 +64,8 @@ void use_semaphor_antipattern_multiple_w dispatch_semaphore_signal(sema1); }); // FIXME: multiple waits on same semaphor should not raise a warning. - dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}} - dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} + dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } void warn_incorrect_order() { @@ -73,7 +73,7 @@ void warn_incorrect_order() { // if out of order. dispatch_semaphore_t sema = dispatch_semaphore_create(0); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} func(^{ dispatch_semaphore_signal(sema); }); @@ -85,7 +85,7 @@ void warn_w_typedef() { func_w_typedef(^{ dispatch_semaphore_signal(sema); }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } void warn_nested_ast() { @@ -100,7 +100,7 @@ void warn_nested_ast() { dispatch_semaphore_signal(sema); }); } - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } void use_semaphore_assignment() { @@ -110,7 +110,7 @@ void use_semaphore_assignment() { func(^{ dispatch_semaphore_signal(sema); }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } void use_semaphore_assignment_init() { @@ -120,7 +120,7 @@ void use_semaphore_assignment_init() { func(^{ dispatch_semaphore_signal(sema); }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } void differentsemaphoreok() { @@ -172,17 +172,17 @@ void warn_with_cast() { func(^{ dispatch_semaphore_signal((int)sema); }); - dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } -@interface Test1 : NSObject +@interface MyInterface1 : NSObject -(void)use_method_warn; -(void)use_objc_callback_warn; -(void)testNoWarn; -(void)acceptBlock:(block_t)callback; @end -@implementation Test1 +@implementation MyInterface1 -(void)use_method_warn { dispatch_semaphore_t sema = dispatch_semaphore_create(0); @@ -190,7 +190,7 @@ void warn_with_cast() { func(^{ dispatch_semaphore_signal(sema); }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } -(void)testNoWarn { @@ -212,23 +212,55 @@ void warn_with_cast() { [self acceptBlock:^{ dispatch_semaphore_signal(sema); }]; - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} } -void use_objc_and_c_callback(Test1 *t) { +void use_objc_and_c_callback(MyInterface1 *t) { dispatch_semaphore_t sema = dispatch_semaphore_create(0); func(^{ dispatch_semaphore_signal(sema); }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} dispatch_semaphore_t sema1 = dispatch_semaphore_create(0); [t acceptBlock:^{ dispatch_semaphore_signal(sema1); }]; - dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}} + dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a semaphore with Grand Central Dispatch creates useless threads and is subject to priority inversion}} +} +@end + +// No warnings: class name contains "test" +@interface Test1 : NSObject +-(void)use_method_warn; +@end + +@implementation Test1 +-(void)use_method_warn { + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + func(^{ + dispatch_semaphore_signal(sema); + }); + dispatch_semaphore_wait(sema, 100); } +@end + +// No warnings: class name contains "mock" +@interface Mock1 : NSObject +-(void)use_method_warn; +@end + +@implementation Mock1 +-(void)use_method_warn { + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + func(^{ + dispatch_semaphore_signal(sema); + }); + dispatch_semaphore_wait(sema, 100); +} @end Removed: cfe/trunk/test/Analysis/gcdasyncsemaphorechecker_test.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/gcdasyncsemaphorechecker_test.m?rev=327308&view=auto ============================================================================== --- cfe/trunk/test/Analysis/gcdasyncsemaphorechecker_test.m (original) +++ cfe/trunk/test/Analysis/gcdasyncsemaphorechecker_test.m (removed) @@ -1,234 +0,0 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.osx.GCDAsyncSemaphore %s -fblocks -verify -typedef signed char BOOL; -@protocol NSObject - (BOOL)isEqual:(id)object; @end -@interface NSObject <NSObject> {} -+(id)alloc; --(id)init; --(id)autorelease; --(id)copy; --(id)retain; -@end - -typedef int dispatch_semaphore_t; -typedef void (^block_t)(); - -dispatch_semaphore_t dispatch_semaphore_create(int); -void dispatch_semaphore_wait(dispatch_semaphore_t, int); -void dispatch_semaphore_signal(dispatch_semaphore_t); - -void func(void (^)(void)); -void func_w_typedef(block_t); - -int coin(); - -void use_semaphor_antipattern() { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema); - }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -// It's OK to use pattern in tests. -// We simply match the containing function name against ^test. -void test_no_warning() { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema); - }); - dispatch_semaphore_wait(sema, 100); -} - -void use_semaphor_antipattern_multiple_times() { - dispatch_semaphore_t sema1 = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema1); - }); - dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}} - - dispatch_semaphore_t sema2 = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema2); - }); - dispatch_semaphore_wait(sema2, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -void use_semaphor_antipattern_multiple_wait() { - dispatch_semaphore_t sema1 = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema1); - }); - // FIXME: multiple waits on same semaphor should not raise a warning. - dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}} - dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -void warn_incorrect_order() { - // FIXME: ASTMatchers do not allow ordered matching, so would match even - // if out of order. - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} - func(^{ - dispatch_semaphore_signal(sema); - }); -} - -void warn_w_typedef() { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - func_w_typedef(^{ - dispatch_semaphore_signal(sema); - }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -void warn_nested_ast() { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - if (coin()) { - func(^{ - dispatch_semaphore_signal(sema); - }); - } else { - func(^{ - dispatch_semaphore_signal(sema); - }); - } - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -void use_semaphore_assignment() { - dispatch_semaphore_t sema; - sema = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema); - }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -void use_semaphore_assignment_init() { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - sema = dispatch_semaphore_create(1); - - func(^{ - dispatch_semaphore_signal(sema); - }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -void differentsemaphoreok() { - dispatch_semaphore_t sema1 = dispatch_semaphore_create(0); - dispatch_semaphore_t sema2 = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema1); - }); - dispatch_semaphore_wait(sema2, 100); // no-warning -} - -void nosignalok() { - dispatch_semaphore_t sema1 = dispatch_semaphore_create(0); - dispatch_semaphore_wait(sema1, 100); -} - -void nowaitok() { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - func(^{ - dispatch_semaphore_signal(sema); - }); -} - -void noblockok() { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - dispatch_semaphore_signal(sema); - dispatch_semaphore_wait(sema, 100); -} - -void storedblockok() { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - block_t b = ^{ - dispatch_semaphore_signal(sema); - }; - dispatch_semaphore_wait(sema, 100); -} - -void passed_semaphore_ok(dispatch_semaphore_t sema) { - func(^{ - dispatch_semaphore_signal(sema); - }); - dispatch_semaphore_wait(sema, 100); -} - -void warn_with_cast() { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal((int)sema); - }); - dispatch_semaphore_wait((int)sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -@interface Test1 : NSObject --(void)use_method_warn; --(void)use_objc_callback_warn; --(void)testNoWarn; --(void)acceptBlock:(block_t)callback; -@end - -@implementation Test1 - --(void)use_method_warn { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema); - }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - --(void)testNoWarn { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema); - }); - dispatch_semaphore_wait(sema, 100); -} - --(void)acceptBlock:(block_t) callback { - callback(); -} - --(void)use_objc_callback_warn { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - [self acceptBlock:^{ - dispatch_semaphore_signal(sema); - }]; - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -void use_objc_and_c_callback(Test1 *t) { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - func(^{ - dispatch_semaphore_signal(sema); - }); - dispatch_semaphore_wait(sema, 100); // expected-warning{{Possible semaphore performance anti-pattern}} - - dispatch_semaphore_t sema1 = dispatch_semaphore_create(0); - - [t acceptBlock:^{ - dispatch_semaphore_signal(sema1); - }]; - dispatch_semaphore_wait(sema1, 100); // expected-warning{{Possible semaphore performance anti-pattern}} -} - -@end _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits