diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1944,6 +1944,12 @@ } } + // Don't warn about __block Objective-C pointer variables, as they might + // be assigned in the block but not used elsewhere for the purpose of lifetime + // extension. + if (VD->hasAttr() && Ty->isObjCObjectPointerType()) + return; + auto iter = RefsMinusAssignments.find(VD); if (iter == RefsMinusAssignments.end()) return; diff --git a/clang/test/SemaObjC/block-capture-unused-variable.m b/clang/test/SemaObjC/block-capture-unused-variable.m new file mode 100644 --- /dev/null +++ b/clang/test/SemaObjC/block-capture-unused-variable.m @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macos11 -fsyntax-only -fobjc-arc -fblocks -verify -Wunused-but-set-variable -Wno-objc-root-class %s + +typedef struct dispatch_queue_s *dispatch_queue_t; + +typedef void (^dispatch_block_t)(void); + +void dispatch_async(dispatch_queue_t queue, dispatch_block_t block); + +extern __attribute__((visibility("default"))) struct dispatch_queue_s _dispatch_main_q; + +id getFoo(); + +@protocol P + +@end + +@interface I + +@end + +void test() { + // no diagnostics + __block id x = getFoo(); + __block id

y = x; + __block I *z = (I *)x; + // diagnose non-block variables + id x2 = getFoo(); // expected-warning {{variable 'x2' set but not used}} + dispatch_async(&_dispatch_main_q, ^{ + x = ((void *)0); + y = x; + z = ((void *)0); + }); + x2 = getFoo(); +}