xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-goto.cpp (revision 89a1d03e2b379e325daa5249411e414bbd995b5e)
1*89a1d03eSRichard // RUN: %check_clang_tidy %s cppcoreguidelines-avoid-goto %t
2*89a1d03eSRichard 
noop()3*89a1d03eSRichard void noop() {}
4*89a1d03eSRichard 
main()5*89a1d03eSRichard int main() {
6*89a1d03eSRichard   noop();
7*89a1d03eSRichard   goto jump_to_me;
8*89a1d03eSRichard   // CHECK-NOTES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
9*89a1d03eSRichard   // CHECK-NOTES: [[@LINE+3]]:1: note: label defined here
10*89a1d03eSRichard   noop();
11*89a1d03eSRichard 
12*89a1d03eSRichard jump_to_me:;
13*89a1d03eSRichard 
14*89a1d03eSRichard jump_backwards:;
15*89a1d03eSRichard   noop();
16*89a1d03eSRichard   goto jump_backwards;
17*89a1d03eSRichard   // CHECK-NOTES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
18*89a1d03eSRichard   // CHECK-NOTES: [[@LINE-4]]:1: note: label defined here
19*89a1d03eSRichard 
20*89a1d03eSRichard   goto jump_in_line;
21*89a1d03eSRichard   ;
22*89a1d03eSRichard jump_in_line:;
23*89a1d03eSRichard   // CHECK-NOTES: [[@LINE-3]]:3: warning: avoid using 'goto' for flow control
24*89a1d03eSRichard   // CHECK-NOTES: [[@LINE-2]]:1: note: label defined here
25*89a1d03eSRichard 
26*89a1d03eSRichard   // Test the GNU extension https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
27*89a1d03eSRichard some_label:;
28*89a1d03eSRichard   void *dynamic_label = &&some_label;
29*89a1d03eSRichard 
30*89a1d03eSRichard   // FIXME: `IndirectGotoStmt` is not detected.
31*89a1d03eSRichard   goto *dynamic_label;
32*89a1d03eSRichard }
33*89a1d03eSRichard 
forward_jump_out_nested_loop()34*89a1d03eSRichard void forward_jump_out_nested_loop() {
35*89a1d03eSRichard   int array[] = {1, 2, 3, 4, 5};
36*89a1d03eSRichard   for (int i = 0; i < 10; ++i) {
37*89a1d03eSRichard     noop();
38*89a1d03eSRichard     for (int j = 0; j < 10; ++j) {
39*89a1d03eSRichard       noop();
40*89a1d03eSRichard       if (i + j > 10)
41*89a1d03eSRichard         goto early_exit1;
42*89a1d03eSRichard     }
43*89a1d03eSRichard     noop();
44*89a1d03eSRichard   }
45*89a1d03eSRichard 
46*89a1d03eSRichard   for (int i = 0; i < 10; ++i) {
47*89a1d03eSRichard     noop();
48*89a1d03eSRichard     while (true) {
49*89a1d03eSRichard       noop();
50*89a1d03eSRichard       if (i > 5)
51*89a1d03eSRichard         goto early_exit1;
52*89a1d03eSRichard     }
53*89a1d03eSRichard     noop();
54*89a1d03eSRichard   }
55*89a1d03eSRichard 
56*89a1d03eSRichard   for (auto value : array) {
57*89a1d03eSRichard     noop();
58*89a1d03eSRichard     for (auto number : array) {
59*89a1d03eSRichard       noop();
60*89a1d03eSRichard       if (number == 5)
61*89a1d03eSRichard         goto early_exit1;
62*89a1d03eSRichard     }
63*89a1d03eSRichard   }
64*89a1d03eSRichard 
65*89a1d03eSRichard   do {
66*89a1d03eSRichard     noop();
67*89a1d03eSRichard     do {
68*89a1d03eSRichard       noop();
69*89a1d03eSRichard       goto early_exit1;
70*89a1d03eSRichard     } while (true);
71*89a1d03eSRichard   } while (true);
72*89a1d03eSRichard 
73*89a1d03eSRichard   do {
74*89a1d03eSRichard     for (auto number : array) {
75*89a1d03eSRichard       noop();
76*89a1d03eSRichard       if (number == 2)
77*89a1d03eSRichard         goto early_exit1;
78*89a1d03eSRichard     }
79*89a1d03eSRichard   } while (true);
80*89a1d03eSRichard 
81*89a1d03eSRichard   // Jumping further results in error, because the variable declaration would
82*89a1d03eSRichard   // be skipped.
83*89a1d03eSRichard early_exit1:;
84*89a1d03eSRichard 
85*89a1d03eSRichard   int i = 0;
86*89a1d03eSRichard   while (true) {
87*89a1d03eSRichard     noop();
88*89a1d03eSRichard     while (true) {
89*89a1d03eSRichard       noop();
90*89a1d03eSRichard       if (i > 5)
91*89a1d03eSRichard         goto early_exit2;
92*89a1d03eSRichard       i++;
93*89a1d03eSRichard     }
94*89a1d03eSRichard     noop();
95*89a1d03eSRichard   }
96*89a1d03eSRichard 
97*89a1d03eSRichard   while (true) {
98*89a1d03eSRichard     noop();
99*89a1d03eSRichard     for (int j = 0; j < 10; ++j) {
100*89a1d03eSRichard       noop();
101*89a1d03eSRichard       if (j > 5)
102*89a1d03eSRichard         goto early_exit2;
103*89a1d03eSRichard     }
104*89a1d03eSRichard     noop();
105*89a1d03eSRichard   }
106*89a1d03eSRichard 
107*89a1d03eSRichard   while (true) {
108*89a1d03eSRichard     noop();
109*89a1d03eSRichard     for (auto number : array) {
110*89a1d03eSRichard       if (number == 1)
111*89a1d03eSRichard         goto early_exit2;
112*89a1d03eSRichard       noop();
113*89a1d03eSRichard     }
114*89a1d03eSRichard   }
115*89a1d03eSRichard 
116*89a1d03eSRichard   while (true) {
117*89a1d03eSRichard     noop();
118*89a1d03eSRichard     do {
119*89a1d03eSRichard       noop();
120*89a1d03eSRichard       goto early_exit2;
121*89a1d03eSRichard     } while (true);
122*89a1d03eSRichard   }
123*89a1d03eSRichard early_exit2:;
124*89a1d03eSRichard }
125*89a1d03eSRichard 
jump_out_backwards()126*89a1d03eSRichard void jump_out_backwards() {
127*89a1d03eSRichard 
128*89a1d03eSRichard before_the_loop:
129*89a1d03eSRichard   noop();
130*89a1d03eSRichard 
131*89a1d03eSRichard   for (int i = 0; i < 10; ++i) {
132*89a1d03eSRichard     for (int j = 0; j < 10; ++j) {
133*89a1d03eSRichard       if (i * j > 80)
134*89a1d03eSRichard         goto before_the_loop;
135*89a1d03eSRichard       // CHECK-NOTES: [[@LINE-1]]:9: warning: avoid using 'goto' for flow control
136*89a1d03eSRichard       // CHECK-NOTES: [[@LINE-8]]:1: note: label defined here
137*89a1d03eSRichard     }
138*89a1d03eSRichard   }
139*89a1d03eSRichard }
140