Index: lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp +++ lib/StaticAnalyzer/Checkers/GCDAsyncSemaphoreChecker.cpp @@ -111,23 +111,26 @@ ) ).bind(WarningBinding)); - auto AcceptsBlockM = - forEachDescendant(callExpr(hasAnyArgument(hasType( + auto HasBlockArgumentM = hasAnyArgument(hasType( hasCanonicalType(blockPointerType()) - )))); + )); - auto BlockSignallingM = - forEachDescendant(callExpr(hasAnyArgument(hasDescendant(callExpr( + auto ArgCallsSignalM = hasArgument(0, hasDescendant(callExpr( allOf( callsName("dispatch_semaphore_signal"), equalsBoundArgDecl(0, SemaphoreBinding) - )))))); + )))); + + auto HasBlockAndCallsSignalM = allOf(HasBlockArgumentM, ArgCallsSignalM); + + auto AcceptsBlockM = + anyOf( + forEachDescendant(callExpr(HasBlockAndCallsSignalM)), + forEachDescendant(objcMessageExpr(HasBlockAndCallsSignalM)) + ); + - auto FinalM = compoundStmt( - SemaphoreBindingM, - SemaphoreWaitM, - AcceptsBlockM, - BlockSignallingM); + auto FinalM = compoundStmt(SemaphoreBindingM, SemaphoreWaitM, AcceptsBlockM); MatchFinder F; Callback CB(BR, AM.getAnalysisDeclContext(D), this); Index: test/Analysis/gcdasyncsemaphorechecker_test.m =================================================================== --- test/Analysis/gcdasyncsemaphorechecker_test.m +++ test/Analysis/gcdasyncsemaphorechecker_test.m @@ -177,7 +177,9 @@ @interface Test1 : NSObject -(void)use_method_warn; +-(void)use_objc_callback_warn; -(void)testNoWarn; +-(void)acceptBlock:(block_t)callback; @end @implementation Test1 @@ -200,4 +202,18 @@ 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}} + +} + @end