forked from OSchip/llvm-project
180 lines
8.7 KiB
C++
180 lines
8.7 KiB
C++
// RUN: %check_clang_tidy %s misc-no-recursion %t
|
|
|
|
// We don't have the definition of this function,
|
|
// so we can't tell anything about it..
|
|
void external();
|
|
|
|
// This function is obviously not recursive.
|
|
void no_recursion() {
|
|
}
|
|
|
|
// Since we don't know what `external()` does,
|
|
// we don't know if this is recursive or not.
|
|
void maybe_no_recursion() {
|
|
external();
|
|
}
|
|
|
|
// Function calls itself - obviously a recursion.
|
|
void endless_recursion() {
|
|
endless_recursion();
|
|
}
|
|
|
|
// CHECK-NOTES: :[[@LINE-4]]:6: warning: function 'endless_recursion' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-5]]:6: note: example recursive call chain, starting from function 'endless_recursion'
|
|
// CHECK-NOTES: :[[@LINE-5]]:3: note: Frame #1: function 'endless_recursion' calls function 'endless_recursion' here:
|
|
// CHECK-NOTES: :[[@LINE-6]]:3: note: ... which was the starting point of the recursive call chain; there may be other cycles
|
|
|
|
bool external_oracle();
|
|
bool another_external_oracle();
|
|
|
|
// Function calls itself if some external function said so - recursion.
|
|
void maybe_endless_recursion() {
|
|
if (external_oracle())
|
|
maybe_endless_recursion();
|
|
}
|
|
|
|
// CHECK-NOTES: :[[@LINE-5]]:6: warning: function 'maybe_endless_recursion' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-6]]:6: note: example recursive call chain, starting from function 'maybe_endless_recursion'
|
|
// CHECK-NOTES: :[[@LINE-5]]:5: note: Frame #1: function 'maybe_endless_recursion' calls function 'maybe_endless_recursion' here:
|
|
// CHECK-NOTES: :[[@LINE-6]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
|
|
|
|
// Obviously-constrained recursion.
|
|
void recursive_countdown(unsigned x) {
|
|
if (x == 0)
|
|
return;
|
|
recursive_countdown(x - 1);
|
|
}
|
|
|
|
// CHECK-NOTES: :[[@LINE-6]]:6: warning: function 'recursive_countdown' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-7]]:6: note: example recursive call chain, starting from function 'recursive_countdown'
|
|
// CHECK-NOTES: :[[@LINE-5]]:3: note: Frame #1: function 'recursive_countdown' calls function 'recursive_countdown' here:
|
|
// CHECK-NOTES: :[[@LINE-6]]:3: note: ... which was the starting point of the recursive call chain; there may be other cycles
|
|
|
|
void indirect_recursion();
|
|
void conditionally_executed() {
|
|
if (external_oracle())
|
|
indirect_recursion();
|
|
}
|
|
void indirect_recursion() {
|
|
if (external_oracle())
|
|
conditionally_executed();
|
|
}
|
|
|
|
// CHECK-NOTES: :[[@LINE-9]]:6: warning: function 'conditionally_executed' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-6]]:6: note: example recursive call chain, starting from function 'indirect_recursion'
|
|
// CHECK-NOTES: :[[@LINE-5]]:5: note: Frame #1: function 'indirect_recursion' calls function 'conditionally_executed' here:
|
|
// CHECK-NOTES: :[[@LINE-10]]:5: note: Frame #2: function 'conditionally_executed' calls function 'indirect_recursion' here:
|
|
// CHECK-NOTES: :[[@LINE-11]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
|
|
// CHECK-NOTES: :[[@LINE-10]]:6: warning: function 'indirect_recursion' is within a recursive call chain [misc-no-recursion]
|
|
|
|
void taint();
|
|
void maybe_selfrecursion_with_two_backedges() {
|
|
if (external_oracle())
|
|
maybe_selfrecursion_with_two_backedges();
|
|
taint();
|
|
if (another_external_oracle())
|
|
maybe_selfrecursion_with_two_backedges();
|
|
}
|
|
|
|
// CHECK-NOTES: :[[@LINE-8]]:6: warning: function 'maybe_selfrecursion_with_two_backedges' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-9]]:6: note: example recursive call chain, starting from function 'maybe_selfrecursion_with_two_backedges'
|
|
// CHECK-NOTES: :[[@LINE-8]]:5: note: Frame #1: function 'maybe_selfrecursion_with_two_backedges' calls function 'maybe_selfrecursion_with_two_backedges' here:
|
|
// CHECK-NOTES: :[[@LINE-9]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
|
|
|
|
void indirect_recursion_with_alternatives();
|
|
void conditionally_executed_choice_0() {
|
|
if (external_oracle())
|
|
indirect_recursion_with_alternatives();
|
|
}
|
|
void conditionally_executed_choice_1() {
|
|
if (external_oracle())
|
|
indirect_recursion_with_alternatives();
|
|
}
|
|
void indirect_recursion_with_alternatives() {
|
|
if (external_oracle())
|
|
conditionally_executed_choice_0();
|
|
else
|
|
conditionally_executed_choice_1();
|
|
}
|
|
|
|
// CHECK-NOTES: :[[@LINE-15]]:6: warning: function 'conditionally_executed_choice_0' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-8]]:6: note: example recursive call chain, starting from function 'indirect_recursion_with_alternatives'
|
|
// CHECK-NOTES: :[[@LINE-7]]:5: note: Frame #1: function 'indirect_recursion_with_alternatives' calls function 'conditionally_executed_choice_0' here:
|
|
// CHECK-NOTES: :[[@LINE-16]]:5: note: Frame #2: function 'conditionally_executed_choice_0' calls function 'indirect_recursion_with_alternatives' here:
|
|
// CHECK-NOTES: :[[@LINE-17]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
|
|
// CHECK-NOTES: :[[@LINE-16]]:6: warning: function 'conditionally_executed_choice_1' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-13]]:6: warning: function 'indirect_recursion_with_alternatives' is within a recursive call chain [misc-no-recursion]
|
|
|
|
static void indirect_recursion_with_depth2();
|
|
static void conditionally_executed_depth1() {
|
|
if (external_oracle())
|
|
indirect_recursion_with_depth2();
|
|
}
|
|
static void conditionally_executed_depth0() {
|
|
if (external_oracle())
|
|
conditionally_executed_depth1();
|
|
}
|
|
void indirect_recursion_with_depth2() {
|
|
if (external_oracle())
|
|
conditionally_executed_depth0();
|
|
}
|
|
|
|
// CHECK-NOTES: :[[@LINE-13]]:13: warning: function 'conditionally_executed_depth1' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-10]]:13: note: example recursive call chain, starting from function 'conditionally_executed_depth0'
|
|
// CHECK-NOTES: :[[@LINE-9]]:5: note: Frame #1: function 'conditionally_executed_depth0' calls function 'conditionally_executed_depth1' here:
|
|
// CHECK-NOTES: :[[@LINE-14]]:5: note: Frame #2: function 'conditionally_executed_depth1' calls function 'indirect_recursion_with_depth2' here:
|
|
// CHECK-NOTES: :[[@LINE-7]]:5: note: Frame #3: function 'indirect_recursion_with_depth2' calls function 'conditionally_executed_depth0' here:
|
|
// CHECK-NOTES: :[[@LINE-8]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
|
|
// CHECK-NOTES: :[[@LINE-15]]:13: warning: function 'conditionally_executed_depth0' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-12]]:6: warning: function 'indirect_recursion_with_depth2' is within a recursive call chain [misc-no-recursion]
|
|
|
|
int boo();
|
|
void foo(int x = boo()) {}
|
|
void bar() {
|
|
foo();
|
|
foo();
|
|
}
|
|
int boo() {
|
|
bar();
|
|
return 0;
|
|
}
|
|
|
|
// CHECK-NOTES: :[[@LINE-9]]:6: warning: function 'bar' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-6]]:5: note: example recursive call chain, starting from function 'boo'
|
|
// CHECK-NOTES: :[[@LINE-6]]:3: note: Frame #1: function 'boo' calls function 'bar' here:
|
|
// CHECK-NOTES: :[[@LINE-13]]:18: note: Frame #2: function 'bar' calls function 'boo' here:
|
|
// CHECK-NOTES: :[[@LINE-14]]:18: note: ... which was the starting point of the recursive call chain; there may be other cycles
|
|
// CHECK-NOTES: :[[@LINE-10]]:5: warning: function 'boo' is within a recursive call chain [misc-no-recursion]
|
|
|
|
int recursion_through_function_ptr() {
|
|
auto *ptr = &recursion_through_function_ptr;
|
|
if (external_oracle())
|
|
return ptr();
|
|
return 0;
|
|
}
|
|
|
|
int recursion_through_lambda() {
|
|
auto zz = []() {
|
|
if (external_oracle())
|
|
return recursion_through_lambda();
|
|
return 0;
|
|
};
|
|
return zz();
|
|
}
|
|
|
|
// CHECK-NOTES: :[[@LINE-9]]:5: warning: function 'recursion_through_lambda' is within a recursive call chain [misc-no-recursion]
|
|
// CHECK-NOTES: :[[@LINE-9]]:13: note: example recursive call chain, starting from function 'operator()'
|
|
// CHECK-NOTES: :[[@LINE-8]]:14: note: Frame #1: function 'operator()' calls function 'recursion_through_lambda' here:
|
|
// CHECK-NOTES: :[[@LINE-6]]:10: note: Frame #2: function 'recursion_through_lambda' calls function 'operator()' here:
|
|
// CHECK-NOTES: :[[@LINE-7]]:10: note: ... which was the starting point of the recursive call chain; there may be other cycles
|
|
// CHECK-NOTES: :[[@LINE-13]]:13: warning: function 'operator()' is within a recursive call chain [misc-no-recursion]
|
|
|
|
struct recursion_through_destructor {
|
|
~recursion_through_destructor() {
|
|
if (external_oracle()) {
|
|
recursion_through_destructor variable;
|
|
// variable goes out of scope, it's destructor runs, and we are back here.
|
|
}
|
|
}
|
|
};
|