diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2021-05-11 16:44:49 -0700 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2021-05-13 11:25:02 -0700 |
commit | 5ad2eeeadaf15856332f66ed7c244d52a86b0be7 (patch) | |
tree | 7a81771ede4eb1059600366b220ff759e063bc3a | |
parent | 46c6c08c9428a36bdf88f51b1a14164aa4cbb93e (diff) | |
download | llvm-5ad2eeeadaf15856332f66ed7c244d52a86b0be7.zip llvm-5ad2eeeadaf15856332f66ed7c244d52a86b0be7.tar.gz llvm-5ad2eeeadaf15856332f66ed7c244d52a86b0be7.tar.bz2 |
[clang-tidy] bugprone-infinite-loop: React to ObjC ivars and messages.
If the loop condition is a value of an instance variable, a property value,
or a message result value, it's a good indication that the loop is not infinite
and we have a really hard time proving the opposite so suppress the warning.
Differential Revision: https://reviews.llvm.org/D102294
-rw-r--r-- | clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp | 3 | ||||
-rw-r--r-- | clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.mm | 90 |
2 files changed, 92 insertions, 1 deletions
diff --git a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp index ab62b12..8ac7f8e 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp @@ -61,7 +61,8 @@ static bool isVarThatIsPossiblyChanged(const Decl *Func, const Stmt *LoopStmt, isChanged(LoopStmt, Var, Context); // FIXME: Track references. } - } else if (isa<MemberExpr>(Cond) || isa<CallExpr>(Cond)) { + } else if (isa<MemberExpr, CallExpr, + ObjCIvarRefExpr, ObjCPropertyRefExpr, ObjCMessageExpr>(Cond)) { // FIXME: Handle MemberExpr. return true; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.mm b/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.mm index 77d85ac..8f157b3 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.mm +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.mm @@ -1,8 +1,20 @@ // RUN: %check_clang_tidy %s bugprone-infinite-loop %t -- -- -fblocks +// RUN: %check_clang_tidy %s bugprone-infinite-loop %t -- -- -fblocks -fobjc-arc + +typedef __typeof(sizeof(int)) NSUInteger; + +@interface NSArray ++(instancetype)alloc; +-(instancetype)init; +@property(readonly) NSUInteger count; +-(void)addObject: (id)anObject; +@end @interface I -(void) instanceMethod; +(void) classMethod; ++(instancetype)alloc; +-(instancetype)init; @end void plainCFunction() { @@ -33,3 +45,81 @@ void plainCFunction() { } } @end + +void testArrayCount() { + NSArray *arr = [[NSArray alloc] init]; + NSUInteger max_count = 10; + while ([arr count] < max_count) { + // No warning. Array count is updated on every iteration. + [arr addObject: [[I alloc] init]]; + } +} + +void testArrayCountWithConstant() { + NSArray *arr = [[NSArray alloc] init]; + while ([arr count] < 10) { + // No warning. Array count is updated on every iteration. + [arr addObject: [[I alloc] init]]; + } +} + +void testArrayCountProperty() { + NSArray *arr = [[NSArray alloc] init]; + NSUInteger max_count = 10; + while (arr.count < max_count) { + // No warning. Array count is updated on every iteration. + [arr addObject: [[I alloc] init]]; + } +} + +void testArrayCountPropertyWithConstant() { + NSArray *arr = [[NSArray alloc] init]; + while (arr.count < 10) { + // No warning. Array count is updated on every iteration. + [arr addObject: [[I alloc] init]]; + } +} + +@interface MyArray { + @public NSUInteger _count; +} ++(instancetype)alloc; +-(instancetype)init; +-(void)addObject: (id)anObject; + +-(void)populate; +@end + +@implementation MyArray +-(void)populate { + NSUInteger max_count = 10; + while (_count < max_count) { + // No warning. Array count is updated on every iteration. + [self addObject: [[I alloc] init]]; + } +} + +-(void)populateWithConstant { + while (_count < 10) { + // No warning. Array count is updated on every iteration. + [self addObject: [[I alloc] init]]; + } +} +@end + +void testArrayCountIvar() { + MyArray *arr = [[MyArray alloc] init]; + NSUInteger max_count = 10; + while (arr->_count < max_count) { + // No warning. Array count is updated on every iteration. + [arr addObject: [[I alloc] init]]; + } +} + +void testArrayCountIvarWithConstant() { + MyArray *arr = [[MyArray alloc] init]; + while (arr->_count < 10) { + // No warning. Array count is updated on every iteration. + [arr addObject: [[I alloc] init]]; + } +} |