// 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:; }