Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion c/misra/test/rules/RULE-17-2/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ void f3() {
f3(); // NON_COMPLIANT
}
void f6() {
f3(); // NON_COMPLIANT
f3(); // COMPLIANT - merely calls a recursive function
}

void f5() {
Expand Down
2 changes: 2 additions & 0 deletions change_notes/2026-06-18-fix-fp-recursive-functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
`A7-5-2`, `RULE-8-2-10`: `FunctionsCallThemselvesEitherDirectlyOrIndirectly.ql`:
- Fix false positives where callers of recursive functions were incorrectly reported as recursive. Only calls that participate in a recursive cycle are now reported.
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ class RecursiveFunction extends Function {
RecursiveFunction() { exists(RecursiveCall fc | fc.getEnclosingFunction() = this) }
}

query predicate problems(FunctionCall fc, string message, RecursiveFunction f, string functionName) {
query predicate problems(RecursiveCall fc, string message, Function f, string functionName) {
not isExcluded(fc, getQuery()) and
f = fc.getTarget() and
functionName = f.getName() and
if f = fc.getEnclosingFunction()
then message = "This call directly invokes its containing function $@."
else
message =
"The function " + fc.getEnclosingFunction() + " is indirectly recursive via this call to $@."
"The function " + fc.getEnclosingFunction() +
" is indirectly recursive via this call to $@."
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
| test.cpp:7:13:7:35 | call to test_recursive_function | This call directly invokes its containing function $@. | test.cpp:5:5:5:27 | test_recursive_function | test_recursive_function |
| test.cpp:21:9:21:31 | call to test_recursive_function | The function test_indirect_recursive_function is indirectly recursive via this call to $@. | test.cpp:5:5:5:27 | test_recursive_function | test_recursive_function |
| test.cpp:27:5:27:30 | call to test_indirect_recursive_f2 | The function test_indirect_recursive_f1 is indirectly recursive via this call to $@. | test.cpp:36:5:36:30 | test_indirect_recursive_f2 | test_indirect_recursive_f2 |
| test.cpp:38:9:38:34 | call to test_indirect_recursive_f1 | The function test_indirect_recursive_f2 is indirectly recursive via this call to $@. | test.cpp:25:5:25:30 | test_indirect_recursive_f1 | test_indirect_recursive_f1 |
| test.cpp:75:10:75:19 | call to operator== | This call directly invokes its containing function $@. | test.cpp:74:6:74:15 | operator== | operator== |
| test.cpp:31:5:31:30 | call to test_indirect_recursive_f2 | The function test_indirect_recursive_f1 is indirectly recursive via this call to $@. | test.cpp:40:5:40:30 | test_indirect_recursive_f2 | test_indirect_recursive_f2 |
| test.cpp:42:9:42:34 | call to test_indirect_recursive_f1 | The function test_indirect_recursive_f2 is indirectly recursive via this call to $@. | test.cpp:29:5:29:30 | test_indirect_recursive_f1 | test_indirect_recursive_f1 |
| test.cpp:79:10:79:19 | call to operator== | This call directly invokes its containing function $@. | test.cpp:78:6:78:15 | operator== | operator== |
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ int test_nonrecursive_function(int i) { // COMPLIANT

int test_indirect_recursive_function(int i) {
if (i > 10) {
i = test_recursive_function(i * i); // NON_COMPLIANT
i = test_recursive_function(i * i); // COMPLIANT - merely calls a recursive function
}
}

int test_calls_recursive_function(int i) {
return test_recursive_function(i); // COMPLIANT - not part of a recursive cycle
}

int test_indirect_recursive_f1(int i) {
if (i > 10) {
test_indirect_recursive_f2(i + i); // NON_COMPLIANT
Expand Down