1 | // RUN: %check_clang_tidy %s bugprone-infinite-loop %t -- -- -fblocks |
2 | // RUN: %check_clang_tidy %s bugprone-infinite-loop %t -- -- -fblocks -fobjc-arc |
3 | |
4 | typedef __typeof(sizeof(int)) NSUInteger; |
5 | |
6 | @interface NSArray |
7 | +(instancetype)alloc; |
8 | -(instancetype)init; |
9 | @property(readonly) NSUInteger count; |
10 | -(void)addObject: (id)anObject; |
11 | @end |
12 | |
13 | @interface I |
14 | -(void) instanceMethod; |
15 | +(void) classMethod; |
16 | +(instancetype)alloc; |
17 | -(instancetype)init; |
18 | @end |
19 | |
20 | void plainCFunction() { |
21 | int i = 0; |
22 | int j = 0; |
23 | while (i < 10) { |
24 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop] |
25 | j++; |
26 | } |
27 | } |
28 | |
29 | @implementation I |
30 | - (void)instanceMethod { |
31 | int i = 0; |
32 | int j = 0; |
33 | while (i < 10) { |
34 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop] |
35 | j++; |
36 | } |
37 | } |
38 | |
39 | + (void)classMethod { |
40 | int i = 0; |
41 | int j = 0; |
42 | while (i < 10) { |
43 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop] |
44 | j++; |
45 | } |
46 | } |
47 | |
48 | + (void)recursiveMethod { |
49 | static int i = 0; |
50 | |
51 | i++; |
52 | while (i < 10) { |
53 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop] |
54 | [I classMethod]; |
55 | } |
56 | |
57 | id x = [[I alloc] init]; |
58 | |
59 | while (i < 10) { |
60 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop] |
61 | [x instanceMethod]; |
62 | } |
63 | while (i < 10) { |
64 | // no warning, there is a recursive call that can mutate the static local variable |
65 | [I recursiveMethod]; |
66 | } |
67 | } |
68 | @end |
69 | |
70 | void testArrayCount() { |
71 | NSArray *arr = [[NSArray alloc] init]; |
72 | NSUInteger max_count = 10; |
73 | while ([arr count] < max_count) { |
74 | // No warning. Array count is updated on every iteration. |
75 | [arr addObject: [[I alloc] init]]; |
76 | } |
77 | } |
78 | |
79 | void testArrayCountWithConstant() { |
80 | NSArray *arr = [[NSArray alloc] init]; |
81 | while ([arr count] < 10) { |
82 | // No warning. Array count is updated on every iteration. |
83 | [arr addObject: [[I alloc] init]]; |
84 | } |
85 | } |
86 | |
87 | void testArrayCountProperty() { |
88 | NSArray *arr = [[NSArray alloc] init]; |
89 | NSUInteger max_count = 10; |
90 | while (arr.count < max_count) { |
91 | // No warning. Array count is updated on every iteration. |
92 | [arr addObject: [[I alloc] init]]; |
93 | } |
94 | } |
95 | |
96 | void testArrayCountPropertyWithConstant() { |
97 | NSArray *arr = [[NSArray alloc] init]; |
98 | while (arr.count < 10) { |
99 | // No warning. Array count is updated on every iteration. |
100 | [arr addObject: [[I alloc] init]]; |
101 | } |
102 | } |
103 | |
104 | @interface MyArray { |
105 | @public NSUInteger _count; |
106 | } |
107 | +(instancetype)alloc; |
108 | -(instancetype)init; |
109 | -(void)addObject: (id)anObject; |
110 | |
111 | -(void)populate; |
112 | @end |
113 | |
114 | @implementation MyArray |
115 | -(void)populate { |
116 | NSUInteger max_count = 10; |
117 | while (_count < max_count) { |
118 | // No warning. Array count is updated on every iteration. |
119 | [self addObject: [[I alloc] init]]; |
120 | } |
121 | } |
122 | |
123 | -(void)populateWithConstant { |
124 | while (_count < 10) { |
125 | // No warning. Array count is updated on every iteration. |
126 | [self addObject: [[I alloc] init]]; |
127 | } |
128 | } |
129 | @end |
130 | |
131 | void testArrayCountIvar() { |
132 | MyArray *arr = [[MyArray alloc] init]; |
133 | NSUInteger max_count = 10; |
134 | while (arr->_count < max_count) { |
135 | // No warning. Array count is updated on every iteration. |
136 | [arr addObject: [[I alloc] init]]; |
137 | } |
138 | } |
139 | |
140 | void testArrayCountIvarWithConstant() { |
141 | MyArray *arr = [[MyArray alloc] init]; |
142 | while (arr->_count < 10) { |
143 | // No warning. Array count is updated on every iteration. |
144 | [arr addObject: [[I alloc] init]]; |
145 | } |
146 | } |
147 | |