vsavchenko created this revision. vsavchenko added a reviewer: NoQ. Herald added a subscriber: Charusso. vsavchenko requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
rdar://75704162 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D99601 Files: clang/lib/Analysis/CalledOnceCheck.cpp clang/test/SemaObjC/warn-called-once.m Index: clang/test/SemaObjC/warn-called-once.m =================================================================== --- clang/test/SemaObjC/warn-called-once.m +++ clang/test/SemaObjC/warn-called-once.m @@ -13,6 +13,7 @@ @protocol NSObject @end @interface NSObject <NSObject> +- (instancetype)init; - (id)copy; - (id)class; - autorelease; @@ -1235,4 +1236,13 @@ handler(); // expected-warning{{completion handler is called twice}} } +- (void)initWithAdditions:(int)cond + withCompletion:(void (^)(void))handler { + self = [self init]; + if (self) { + escape(handler); + } + // no-warning +} + @end Index: clang/lib/Analysis/CalledOnceCheck.cpp =================================================================== --- clang/lib/Analysis/CalledOnceCheck.cpp +++ clang/lib/Analysis/CalledOnceCheck.cpp @@ -57,6 +57,7 @@ "WithReplyTo", "WithReply"}; constexpr llvm::StringLiteral CONVENTIONAL_CONDITIONS[] = { "error", "cancel", "shouldCall", "done", "OK", "success"}; +constexpr llvm::StringLiteral INIT_PREFIX = "init"; struct KnownCalledOnceParameter { llvm::StringLiteral FunctionName; @@ -1011,11 +1012,16 @@ return llvm::None; } + /// Return true if the specified selector represents init method. + static bool isInitMethod(Selector MethodSelector) { + return MethodSelector.getNameForSlot(0).startswith_lower(INIT_PREFIX); + } + /// Return true if the specified selector piece matches conventions. static bool isConventionalSelectorPiece(Selector MethodSelector, unsigned PieceIndex, QualType PieceType) { - if (!isConventional(PieceType)) { + if (!isConventional(PieceType) || isInitMethod(MethodSelector)) { return false; }
Index: clang/test/SemaObjC/warn-called-once.m =================================================================== --- clang/test/SemaObjC/warn-called-once.m +++ clang/test/SemaObjC/warn-called-once.m @@ -13,6 +13,7 @@ @protocol NSObject @end @interface NSObject <NSObject> +- (instancetype)init; - (id)copy; - (id)class; - autorelease; @@ -1235,4 +1236,13 @@ handler(); // expected-warning{{completion handler is called twice}} } +- (void)initWithAdditions:(int)cond + withCompletion:(void (^)(void))handler { + self = [self init]; + if (self) { + escape(handler); + } + // no-warning +} + @end Index: clang/lib/Analysis/CalledOnceCheck.cpp =================================================================== --- clang/lib/Analysis/CalledOnceCheck.cpp +++ clang/lib/Analysis/CalledOnceCheck.cpp @@ -57,6 +57,7 @@ "WithReplyTo", "WithReply"}; constexpr llvm::StringLiteral CONVENTIONAL_CONDITIONS[] = { "error", "cancel", "shouldCall", "done", "OK", "success"}; +constexpr llvm::StringLiteral INIT_PREFIX = "init"; struct KnownCalledOnceParameter { llvm::StringLiteral FunctionName; @@ -1011,11 +1012,16 @@ return llvm::None; } + /// Return true if the specified selector represents init method. + static bool isInitMethod(Selector MethodSelector) { + return MethodSelector.getNameForSlot(0).startswith_lower(INIT_PREFIX); + } + /// Return true if the specified selector piece matches conventions. static bool isConventionalSelectorPiece(Selector MethodSelector, unsigned PieceIndex, QualType PieceType) { - if (!isConventional(PieceType)) { + if (!isConventional(PieceType) || isInitMethod(MethodSelector)) { return false; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits