180 lines · cpp
1// RUN: %check_clang_tidy %s misc-no-recursion %t2 3// We don't have the definition of this function,4// so we can't tell anything about it..5void external();6 7// This function is obviously not recursive.8void no_recursion() {9}10 11// Since we don't know what `external()` does,12// we don't know if this is recursive or not.13void maybe_no_recursion() {14 external();15}16 17// Function calls itself - obviously a recursion.18void endless_recursion() {19 endless_recursion();20}21 22// CHECK-NOTES: :[[@LINE-4]]:6: warning: function 'endless_recursion' is within a recursive call chain [misc-no-recursion]23// CHECK-NOTES: :[[@LINE-5]]:6: note: example recursive call chain, starting from function 'endless_recursion'24// CHECK-NOTES: :[[@LINE-5]]:3: note: Frame #1: function 'endless_recursion' calls function 'endless_recursion' here:25// CHECK-NOTES: :[[@LINE-6]]:3: note: ... which was the starting point of the recursive call chain; there may be other cycles26 27bool external_oracle();28bool another_external_oracle();29 30// Function calls itself if some external function said so - recursion.31void maybe_endless_recursion() {32 if (external_oracle())33 maybe_endless_recursion();34}35 36// CHECK-NOTES: :[[@LINE-5]]:6: warning: function 'maybe_endless_recursion' is within a recursive call chain [misc-no-recursion]37// CHECK-NOTES: :[[@LINE-6]]:6: note: example recursive call chain, starting from function 'maybe_endless_recursion'38// CHECK-NOTES: :[[@LINE-5]]:5: note: Frame #1: function 'maybe_endless_recursion' calls function 'maybe_endless_recursion' here:39// CHECK-NOTES: :[[@LINE-6]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles40 41// Obviously-constrained recursion.42void recursive_countdown(unsigned x) {43 if (x == 0)44 return;45 recursive_countdown(x - 1);46}47 48// CHECK-NOTES: :[[@LINE-6]]:6: warning: function 'recursive_countdown' is within a recursive call chain [misc-no-recursion]49// CHECK-NOTES: :[[@LINE-7]]:6: note: example recursive call chain, starting from function 'recursive_countdown'50// CHECK-NOTES: :[[@LINE-5]]:3: note: Frame #1: function 'recursive_countdown' calls function 'recursive_countdown' here:51// CHECK-NOTES: :[[@LINE-6]]:3: note: ... which was the starting point of the recursive call chain; there may be other cycles52 53void indirect_recursion();54void conditionally_executed() {55 if (external_oracle())56 indirect_recursion();57}58void indirect_recursion() {59 if (external_oracle())60 conditionally_executed();61}62 63// CHECK-NOTES: :[[@LINE-9]]:6: warning: function 'conditionally_executed' is within a recursive call chain [misc-no-recursion]64// CHECK-NOTES: :[[@LINE-6]]:6: note: example recursive call chain, starting from function 'indirect_recursion'65// CHECK-NOTES: :[[@LINE-5]]:5: note: Frame #1: function 'indirect_recursion' calls function 'conditionally_executed' here:66// CHECK-NOTES: :[[@LINE-10]]:5: note: Frame #2: function 'conditionally_executed' calls function 'indirect_recursion' here:67// CHECK-NOTES: :[[@LINE-11]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles68// CHECK-NOTES: :[[@LINE-10]]:6: warning: function 'indirect_recursion' is within a recursive call chain [misc-no-recursion]69 70void taint();71void maybe_selfrecursion_with_two_backedges() {72 if (external_oracle())73 maybe_selfrecursion_with_two_backedges();74 taint();75 if (another_external_oracle())76 maybe_selfrecursion_with_two_backedges();77}78 79// CHECK-NOTES: :[[@LINE-8]]:6: warning: function 'maybe_selfrecursion_with_two_backedges' is within a recursive call chain [misc-no-recursion]80// CHECK-NOTES: :[[@LINE-9]]:6: note: example recursive call chain, starting from function 'maybe_selfrecursion_with_two_backedges'81// CHECK-NOTES: :[[@LINE-8]]:5: note: Frame #1: function 'maybe_selfrecursion_with_two_backedges' calls function 'maybe_selfrecursion_with_two_backedges' here:82// CHECK-NOTES: :[[@LINE-9]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles83 84void indirect_recursion_with_alternatives();85void conditionally_executed_choice_0() {86 if (external_oracle())87 indirect_recursion_with_alternatives();88}89void conditionally_executed_choice_1() {90 if (external_oracle())91 indirect_recursion_with_alternatives();92}93void indirect_recursion_with_alternatives() {94 if (external_oracle())95 conditionally_executed_choice_0();96 else97 conditionally_executed_choice_1();98}99 100// CHECK-NOTES: :[[@LINE-15]]:6: warning: function 'conditionally_executed_choice_0' is within a recursive call chain [misc-no-recursion]101// CHECK-NOTES: :[[@LINE-8]]:6: note: example recursive call chain, starting from function 'indirect_recursion_with_alternatives'102// CHECK-NOTES: :[[@LINE-7]]:5: note: Frame #1: function 'indirect_recursion_with_alternatives' calls function 'conditionally_executed_choice_0' here:103// CHECK-NOTES: :[[@LINE-16]]:5: note: Frame #2: function 'conditionally_executed_choice_0' calls function 'indirect_recursion_with_alternatives' here:104// CHECK-NOTES: :[[@LINE-17]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles105// CHECK-NOTES: :[[@LINE-16]]:6: warning: function 'conditionally_executed_choice_1' is within a recursive call chain [misc-no-recursion]106// CHECK-NOTES: :[[@LINE-13]]:6: warning: function 'indirect_recursion_with_alternatives' is within a recursive call chain [misc-no-recursion]107 108static void indirect_recursion_with_depth2();109static void conditionally_executed_depth1() {110 if (external_oracle())111 indirect_recursion_with_depth2();112}113static void conditionally_executed_depth0() {114 if (external_oracle())115 conditionally_executed_depth1();116}117void indirect_recursion_with_depth2() {118 if (external_oracle())119 conditionally_executed_depth0();120}121 122// CHECK-NOTES: :[[@LINE-13]]:13: warning: function 'conditionally_executed_depth1' is within a recursive call chain [misc-no-recursion]123// CHECK-NOTES: :[[@LINE-10]]:13: note: example recursive call chain, starting from function 'conditionally_executed_depth0'124// CHECK-NOTES: :[[@LINE-9]]:5: note: Frame #1: function 'conditionally_executed_depth0' calls function 'conditionally_executed_depth1' here:125// CHECK-NOTES: :[[@LINE-14]]:5: note: Frame #2: function 'conditionally_executed_depth1' calls function 'indirect_recursion_with_depth2' here:126// CHECK-NOTES: :[[@LINE-7]]:5: note: Frame #3: function 'indirect_recursion_with_depth2' calls function 'conditionally_executed_depth0' here:127// CHECK-NOTES: :[[@LINE-8]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles128// CHECK-NOTES: :[[@LINE-15]]:13: warning: function 'conditionally_executed_depth0' is within a recursive call chain [misc-no-recursion]129// CHECK-NOTES: :[[@LINE-12]]:6: warning: function 'indirect_recursion_with_depth2' is within a recursive call chain [misc-no-recursion]130 131int boo();132void foo(int x = boo()) {}133void bar() {134 foo();135 foo();136}137int boo() {138 bar();139 return 0;140}141 142// CHECK-NOTES: :[[@LINE-9]]:6: warning: function 'bar' is within a recursive call chain [misc-no-recursion]143// CHECK-NOTES: :[[@LINE-6]]:5: note: example recursive call chain, starting from function 'boo'144// CHECK-NOTES: :[[@LINE-6]]:3: note: Frame #1: function 'boo' calls function 'bar' here:145// CHECK-NOTES: :[[@LINE-13]]:18: note: Frame #2: function 'bar' calls function 'boo' here:146// CHECK-NOTES: :[[@LINE-14]]:18: note: ... which was the starting point of the recursive call chain; there may be other cycles147// CHECK-NOTES: :[[@LINE-10]]:5: warning: function 'boo' is within a recursive call chain [misc-no-recursion]148 149int recursion_through_function_ptr() {150 auto *ptr = &recursion_through_function_ptr;151 if (external_oracle())152 return ptr();153 return 0;154}155 156int recursion_through_lambda() {157 auto zz = []() {158 if (external_oracle())159 return recursion_through_lambda();160 return 0;161 };162 return zz();163}164 165// CHECK-NOTES: :[[@LINE-9]]:5: warning: function 'recursion_through_lambda' is within a recursive call chain [misc-no-recursion]166// CHECK-NOTES: :[[@LINE-9]]:13: note: example recursive call chain, starting from function 'operator()'167// CHECK-NOTES: :[[@LINE-8]]:14: note: Frame #1: function 'operator()' calls function 'recursion_through_lambda' here:168// CHECK-NOTES: :[[@LINE-6]]:10: note: Frame #2: function 'recursion_through_lambda' calls function 'operator()' here:169// CHECK-NOTES: :[[@LINE-7]]:10: note: ... which was the starting point of the recursive call chain; there may be other cycles170// CHECK-NOTES: :[[@LINE-13]]:13: warning: function 'operator()' is within a recursive call chain [misc-no-recursion]171 172struct recursion_through_destructor {173 ~recursion_through_destructor() {174 if (external_oracle()) {175 recursion_through_destructor variable;176 // variable goes out of scope, it's destructor runs, and we are back here.177 }178 }179};180