174 lines
3.5 KiB
C++
174 lines
3.5 KiB
C++
// RUN: %check_clang_tidy -check-suffix=,MACRO %s cppcoreguidelines-avoid-goto %t
|
|
// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-goto %t -- -config="{CheckOptions: { cppcoreguidelines-avoid-goto.IgnoreMacros: true }}"
|
|
|
|
void noop() {}
|
|
|
|
int main() {
|
|
noop();
|
|
goto jump_to_me;
|
|
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
|
|
// CHECK-MESSAGES: [[@LINE+3]]:1: note: label defined here
|
|
noop();
|
|
|
|
jump_to_me:;
|
|
|
|
jump_backwards:;
|
|
noop();
|
|
goto jump_backwards;
|
|
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
|
|
// CHECK-MESSAGES: [[@LINE-4]]:1: note: label defined here
|
|
|
|
goto jump_in_line;
|
|
;
|
|
jump_in_line:;
|
|
// CHECK-MESSAGES: [[@LINE-3]]:3: warning: avoid using 'goto' for flow control
|
|
// CHECK-MESSAGES: [[@LINE-2]]:1: note: label defined here
|
|
|
|
// Test the GNU extension https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
|
|
some_label:;
|
|
void *dynamic_label = &&some_label;
|
|
|
|
// FIXME: `IndirectGotoStmt` is not detected.
|
|
goto *dynamic_label;
|
|
}
|
|
|
|
void forward_jump_out_nested_loop() {
|
|
int array[] = {1, 2, 3, 4, 5};
|
|
for (int i = 0; i < 10; ++i) {
|
|
noop();
|
|
for (int j = 0; j < 10; ++j) {
|
|
noop();
|
|
if (i + j > 10)
|
|
goto early_exit1;
|
|
}
|
|
noop();
|
|
}
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
noop();
|
|
while (true) {
|
|
noop();
|
|
if (i > 5)
|
|
goto early_exit1;
|
|
}
|
|
noop();
|
|
}
|
|
|
|
for (auto value : array) {
|
|
noop();
|
|
for (auto number : array) {
|
|
noop();
|
|
if (number == 5)
|
|
goto early_exit1;
|
|
}
|
|
}
|
|
|
|
do {
|
|
noop();
|
|
do {
|
|
noop();
|
|
goto early_exit1;
|
|
} while (true);
|
|
} while (true);
|
|
|
|
do {
|
|
for (auto number : array) {
|
|
noop();
|
|
if (number == 2)
|
|
goto early_exit1;
|
|
}
|
|
} while (true);
|
|
|
|
// Jumping further results in error, because the variable declaration would
|
|
// be skipped.
|
|
early_exit1:;
|
|
|
|
int i = 0;
|
|
while (true) {
|
|
noop();
|
|
while (true) {
|
|
noop();
|
|
if (i > 5)
|
|
goto early_exit2;
|
|
i++;
|
|
}
|
|
noop();
|
|
}
|
|
|
|
while (true) {
|
|
noop();
|
|
for (int j = 0; j < 10; ++j) {
|
|
noop();
|
|
if (j > 5)
|
|
goto early_exit2;
|
|
}
|
|
noop();
|
|
}
|
|
|
|
while (true) {
|
|
noop();
|
|
for (auto number : array) {
|
|
if (number == 1)
|
|
goto early_exit2;
|
|
noop();
|
|
}
|
|
}
|
|
|
|
while (true) {
|
|
noop();
|
|
do {
|
|
noop();
|
|
goto early_exit2;
|
|
} while (true);
|
|
}
|
|
early_exit2:;
|
|
}
|
|
|
|
void jump_out_backwards() {
|
|
|
|
before_the_loop:
|
|
noop();
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
for (int j = 0; j < 10; ++j) {
|
|
if (i * j > 80)
|
|
goto before_the_loop;
|
|
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: avoid using 'goto' for flow control
|
|
// CHECK-MESSAGES: [[@LINE-8]]:1: note: label defined here
|
|
}
|
|
}
|
|
}
|
|
|
|
#define macro_goto_code \
|
|
noop(); \
|
|
goto jump_to_me; \
|
|
noop(); \
|
|
jump_to_me:; \
|
|
|
|
#define macro_goto_label jump_to_me:;
|
|
#define macro_goto_jump goto jump_to_me;
|
|
|
|
void inside_macro_all() {
|
|
macro_goto_code
|
|
// CHECK-MESSAGES-MACRO: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
|
|
// CHECK-MESSAGES-MACRO: [[@LINE-2]]:3: note: label defined here
|
|
}
|
|
|
|
void inside_macro_label() {
|
|
noop();
|
|
goto jump_to_me;
|
|
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
|
|
// CHECK-MESSAGES: [[@LINE+2]]:3: note: label defined here
|
|
noop();
|
|
macro_goto_label
|
|
}
|
|
|
|
void inside_macro_goto() {
|
|
noop();
|
|
macro_goto_jump
|
|
// CHECK-MESSAGES-MACRO: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
|
|
// CHECK-MESSAGES-MACRO: [[@LINE+2]]:3: note: label defined here
|
|
noop();
|
|
jump_to_me:;
|
|
}
|