1 // RUN: %check_clang_tidy %s readability-redundant-control-flow %t
2 
3 void g(int i);
4 void j();
5 
f()6 void f() {
7   return;
8 }
9 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement at the end of a function with a void return type [readability-redundant-control-flow]
10 // CHECK-FIXES: {{^}}void f() {{{$}}
11 // CHECK-FIXES-NEXT: {{^ *}$}}
12 
g()13 void g() {
14   f();
15   return;
16 }
17 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
18 // CHECK-FIXES: {{^  }}f();{{$}}
19 // CHECK-FIXES-NEXT: {{^ *}$}}
20 
g(int i)21 void g(int i) {
22   if (i < 0) {
23     return;
24   }
25   if (i < 10) {
26     f();
27   }
28 }
29 
h()30 int h() {
31   return 1;
32 }
33 
j()34 void j() {
35 }
36 
k()37 void k() {
38   for (int i = 0; i < 10; ++i) {
39     continue;
40   }
41 }
42 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement at the end of loop statement
43 // CHECK-FIXES: {{^}}  for (int i = 0; i < 10; ++i) {{{$}}
44 // CHECK-FIXES-NEXT: {{^ *}$}}
45 
k2()46 void k2() {
47   int v[10] = { 0 };
48   for (auto i : v) {
49     continue;
50   }
51 }
52 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
53 // CHECK-FIXES: {{^}}  for (auto i : v) {{{$}}
54 // CHECK-FIXES-NEXT: {{^ *}$}}
55 
m()56 void m() {
57   int i = 0;
58   do {
59     ++i;
60     continue;
61   } while (i < 10);
62 }
63 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
64 // CHECK-FIXES: {{^  do {$}}
65 // CHECK-FIXES-NEXT: {{^}}    ++i;{{$}}
66 // CHECK-FIXES-NEXT: {{^ *}}} while (i < 10);{{$}}
67 
p()68 void p() {
69   int i = 0;
70   while (i < 10) {
71     ++i;
72     continue;
73   }
74 }
75 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
76 // CHECK-FIXES: {{^}}  while (i < 10) {{{$}}
77 // CHECK-FIXES-NEXT: {{^}}    ++i;{{$}}
78 // CHECK-FIXES-NEXT: {{^ *}$}}
79 
im_not_dead(int i)80 void im_not_dead(int i) {
81   if (i > 0) {
82     return;
83   }
84   g();
85 }
86 
im_still_not_dead(int i)87 void im_still_not_dead(int i) {
88   for (int j = 0; j < 10; ++j) {
89     if (i < 10) {
90       continue;
91     }
92     g();
93   }
94 }
95 
im_dead(int i)96 void im_dead(int i) {
97   if (i > 0) {
98     return;
99     g();
100   }
101   g();
102 }
103 
im_still_dead(int i)104 void im_still_dead(int i) {
105   for (int j = 0; j < 10; ++j) {
106     if (i < 10) {
107       continue;
108       g();
109     }
110     g();
111   }
112 }
113 
void_return()114 void void_return() {
115   return g();
116 }
117 
nested_return_unmolested()118 void nested_return_unmolested() {
119   g();
120   {
121     g();
122     return;
123   }
124 }
125 
nested_continue_unmolested()126 void nested_continue_unmolested() {
127   for (int i = 0; i < 10; ++i) {
128     if (i < 5) {
129       continue;
130     }
131   }
132 }
133 
134 #define MACRO_RETURN_UNMOLESTED(fn_)  \
135   (fn_)();                            \
136   return
137 
138 #define MACRO_CONTINUE_UNMOLESTED(x_) \
139   do {                                \
140     for (int i = 0; i < (x_); ++i) {  \
141       continue;                       \
142     }                                 \
143   } while (false)
144 
macro_return()145 void macro_return() {
146   MACRO_RETURN_UNMOLESTED(g);
147 }
148 
macro_continue()149 void macro_continue() {
150   MACRO_CONTINUE_UNMOLESTED(10);
151 }
152 
153 #define MACRO_RETURN_ARG(stmt_) \
154   stmt_
155 
156 #define MACRO_CONTINUE_ARG(stmt_)   \
157   do {                              \
158     for (int i = 0; i < 10; ++i) {  \
159       stmt_;                        \
160     }                               \
161   } while (false)
162 
macro_arg_return()163 void macro_arg_return() {
164   MACRO_RETURN_ARG(return);
165 }
166 
macro_arg_continue()167 void macro_arg_continue() {
168   MACRO_CONTINUE_ARG(continue);
169 }
170 
171 template <typename T>
template_return(T check)172 void template_return(T check) {
173   if (check < T(0)) {
174     return;
175   }
176   return;
177 }
178 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
179 // CHECK-FIXES: {{^}}  if (check < T(0)) {{{$}}
180 // CHECK-FIXES-NEXT: {{^    return;$}}
181 // CHECK-FIXES-NEXT: {{^ *}$}}
182 // CHECK-FIXES-NEXT: {{^ *}$}}
183 
184 template <>
template_return(int check)185 void template_return(int check) {
186   if (check < 0) {
187     return;
188   }
189   return;
190 }
191 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
192 // CHECK-FIXES: {{^}}  if (check < 0) {{{$}}
193 // CHECK-FIXES-NEXT: {{^    return;$}}
194 // CHECK-FIXES-NEXT: {{^ *}$}}
195 // CHECK-FIXES-NEXT: {{^ *}$}}
196 
197 template <typename T>
template_loop(T end)198 void template_loop(T end) {
199   for (T i = 0; i < end; ++i) {
200     continue;
201   }
202 }
203 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
204 // CHECK-FIXES: {{^}}  for (T i = 0; i < end; ++i) {{{$}}
205 // CHECK-FIXES-NEXT: {{^ *}$}}
206 
207 template <>
template_loop(int end)208 void template_loop(int end) {
209   for (int i = 0; i < end; ++i) {
210     continue;
211   }
212 }
213 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
214 // CHECK-FIXES: {{^}}  for (int i = 0; i < end; ++i) {{{$}}
215 // CHECK-FIXES-NEXT: {{^ *}$}}
216 
call_templates()217 void call_templates() {
218   template_return(10);
219   template_return(10.0f);
220   template_return(10.0);
221   template_loop(10);
222   template_loop(10L);
223   template_loop(10U);
224 }
225