From dea8803092eb51c70433b9ea59e24f045a616bd0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 1 Oct 2026 13:01:44 +0100 Subject: [PATCH 1/4] C++: Test complex-block statement thresholds Cover blocks with four sufficiently large nested loops and the three-loop boundary for cpp/complex-block. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../BlockWithTooManyStatements.cpp | 107 ++++++++++++++++++ .../BlockWithTooManyStatements.expected | 2 + .../BlockWithTooManyStatements.qlref | 2 + 3 files changed, 111 insertions(+) create mode 100644 cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.cpp create mode 100644 cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.expected create mode 100644 cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.qlref diff --git a/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.cpp b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.cpp new file mode 100644 index 000000000000..564afacbe149 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.cpp @@ -0,0 +1,107 @@ +void complex_block_one() { + while (true) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } + while (true) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } + while (true) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } + while (true) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } +} // $ Alert + +void complex_block_two() { + for (;;) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } + for (;;) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } + for (;;) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } + for (;;) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } +} // $ Alert + +void three_complex_statements_is_not_enough() { + while (true) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } + while (true) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } + while (true) { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + } +} diff --git a/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.expected b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.expected new file mode 100644 index 000000000000..be756cd2f7ab --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.expected @@ -0,0 +1,2 @@ +| BlockWithTooManyStatements.cpp:1:26:38:1 | { ... } | Block with too many statements (4 complex statements in the block). | +| BlockWithTooManyStatements.cpp:40:26:77:1 | { ... } | Block with too many statements (4 complex statements in the block). | diff --git a/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.qlref b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.qlref new file mode 100644 index 000000000000..95e8a2612635 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.qlref @@ -0,0 +1,2 @@ +query: Best Practices/BlockWithTooManyStatements.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql From 1a733a61ee503fb95bcfcf153cda60e30a021288 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 1 Oct 2026 13:01:59 +0100 Subject: [PATCH 2/4] C++: Test complex-condition operator threshold Exercise alternating logical operations above and at the reporting threshold for cpp/complex-condition. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../ComplexCondition/ComplexCondition.cpp | 16 ++++++++++++++++ .../ComplexCondition/ComplexCondition.expected | 2 ++ .../ComplexCondition/ComplexCondition.qlref | 2 ++ 3 files changed, 20 insertions(+) create mode 100644 cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.cpp create mode 100644 cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.expected create mode 100644 cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.qlref diff --git a/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.cpp b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.cpp new file mode 100644 index 000000000000..7a244ca7ce93 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.cpp @@ -0,0 +1,16 @@ +void complex_condition_one(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h, bool i, bool j, + bool k, bool l) { + if (a && b || c && d || e && f || g && h || i && j || k && l) { // $ Alert + } +} + +void complex_condition_two(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h, bool i, bool j, + bool k, bool l, bool m) { + if (a || b && c || d && e || f && g || h && i || j && k || l && m) { // $ Alert + } +} + +void five_logical_operations_is_not_enough(bool a, bool b, bool c, bool d, bool e, bool f) { + if (a && b || c && d || e && f) { + } +} diff --git a/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.expected b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.expected new file mode 100644 index 000000000000..ad7133c60277 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.expected @@ -0,0 +1,2 @@ +| ComplexCondition.cpp:3:7:3:62 | ... \|\| ... | Complex condition: too many logical operations in this expression. | +| ComplexCondition.cpp:9:7:9:67 | ... \|\| ... | Complex condition: too many logical operations in this expression. | diff --git a/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.qlref b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.qlref new file mode 100644 index 000000000000..156d845994c3 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.qlref @@ -0,0 +1,2 @@ +query: Best Practices/ComplexCondition.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql From c8a09a025fba02c76161e36eb99979d911591c23 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 1 Oct 2026 13:02:24 +0100 Subject: [PATCH 3/4] C++: Test goto target counts Exercise multiple forward and backward targets and a single forward target for cpp/use-of-goto. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Best Practices/UseOfGoto/UseOfGoto.cpp | 41 +++++++++++++++++++ .../UseOfGoto/UseOfGoto.expected | 2 + .../Best Practices/UseOfGoto/UseOfGoto.qlref | 2 + 3 files changed, 45 insertions(+) create mode 100644 cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.cpp create mode 100644 cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.expected create mode 100644 cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.qlref diff --git a/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.cpp b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.cpp new file mode 100644 index 000000000000..cf3bc7d0d4ba --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.cpp @@ -0,0 +1,41 @@ +void multiple_forward_and_backward_targets_one() { // $ Alert + goto forward_one; + goto forward_two; +forward_one: + ; +forward_two: + ; +backward_one: + ; +backward_two: + ; + goto backward_one; + goto backward_two; +} + +void multiple_forward_and_backward_targets_two() { // $ Alert + goto next_one; + goto next_two; +next_one: + ; +next_two: + ; +earlier_one: + ; +earlier_two: + ; + goto earlier_one; + goto earlier_two; +} + +void one_forward_target_is_not_enough() { + goto forward; +forward: + ; +backward_one: + ; +backward_two: + ; + goto backward_one; + goto backward_two; +} diff --git a/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.expected b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.expected new file mode 100644 index 000000000000..f5a4826fbd24 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.expected @@ -0,0 +1,2 @@ +| UseOfGoto.cpp:1:6:1:46 | definition of multiple_forward_and_backward_targets_one | Multiple forward and backward goto statements may make function multiple_forward_and_backward_targets_one hard to understand. | +| UseOfGoto.cpp:16:6:16:46 | definition of multiple_forward_and_backward_targets_two | Multiple forward and backward goto statements may make function multiple_forward_and_backward_targets_two hard to understand. | diff --git a/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.qlref b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.qlref new file mode 100644 index 000000000000..82c5d4f08266 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.qlref @@ -0,0 +1,2 @@ +query: Best Practices/UseOfGoto.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql From b35b1f47364acce0071adb39ec967e3c84b033fb Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 1 Oct 2026 17:18:39 +0100 Subject: [PATCH 4/4] C++: Adjust the tests with thresholds so as to test the extremes, not the tuning of the threshold. --- .../BlockWithTooManyStatements.cpp | 57 ++++++------------- .../BlockWithTooManyStatements.expected | 3 +- .../ComplexCondition/ComplexCondition.cpp | 14 ++--- .../ComplexCondition.expected | 3 +- .../Best Practices/UseOfGoto/UseOfGoto.cpp | 54 +++++++----------- .../UseOfGoto/UseOfGoto.expected | 3 +- 6 files changed, 44 insertions(+), 90 deletions(-) diff --git a/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.cpp b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.cpp index 564afacbe149..dacbdc797eee 100644 --- a/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.cpp +++ b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.cpp @@ -1,4 +1,4 @@ -void complex_block_one() { +void complex_block() { while (true) { int a = 1; int b = 2; @@ -7,6 +7,9 @@ void complex_block_one() { int e = 5; int f = 6; int g = 7; + int h = 8; + int i = 9; + int j = 10; } while (true) { int a = 1; @@ -16,6 +19,9 @@ void complex_block_one() { int e = 5; int f = 6; int g = 7; + int h = 8; + int i = 9; + int j = 10; } while (true) { int a = 1; @@ -25,6 +31,9 @@ void complex_block_one() { int e = 5; int f = 6; int g = 7; + int h = 8; + int i = 9; + int j = 10; } while (true) { int a = 1; @@ -34,38 +43,11 @@ void complex_block_one() { int e = 5; int f = 6; int g = 7; + int h = 8; + int i = 9; + int j = 10; } -} // $ Alert - -void complex_block_two() { - for (;;) { - int a = 1; - int b = 2; - int c = 3; - int d = 4; - int e = 5; - int f = 6; - int g = 7; - } - for (;;) { - int a = 1; - int b = 2; - int c = 3; - int d = 4; - int e = 5; - int f = 6; - int g = 7; - } - for (;;) { - int a = 1; - int b = 2; - int c = 3; - int d = 4; - int e = 5; - int f = 6; - int g = 7; - } - for (;;) { + while (true) { int a = 1; int b = 2; int c = 3; @@ -73,18 +55,19 @@ void complex_block_two() { int e = 5; int f = 6; int g = 7; + int h = 8; + int i = 9; + int j = 10; } } // $ Alert -void three_complex_statements_is_not_enough() { +void not_complex_block() { while (true) { int a = 1; int b = 2; int c = 3; int d = 4; int e = 5; - int f = 6; - int g = 7; } while (true) { int a = 1; @@ -92,8 +75,6 @@ void three_complex_statements_is_not_enough() { int c = 3; int d = 4; int e = 5; - int f = 6; - int g = 7; } while (true) { int a = 1; @@ -101,7 +82,5 @@ void three_complex_statements_is_not_enough() { int c = 3; int d = 4; int e = 5; - int f = 6; - int g = 7; } } diff --git a/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.expected b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.expected index be756cd2f7ab..6243b3a32fa7 100644 --- a/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.expected +++ b/cpp/ql/test/query-tests/Best Practices/BlockWithTooManyStatements/BlockWithTooManyStatements.expected @@ -1,2 +1 @@ -| BlockWithTooManyStatements.cpp:1:26:38:1 | { ... } | Block with too many statements (4 complex statements in the block). | -| BlockWithTooManyStatements.cpp:40:26:77:1 | { ... } | Block with too many statements (4 complex statements in the block). | +| BlockWithTooManyStatements.cpp:1:22:62:1 | { ... } | Block with too many statements (5 complex statements in the block). | diff --git a/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.cpp b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.cpp index 7a244ca7ce93..0322cddc2d7a 100644 --- a/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.cpp +++ b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.cpp @@ -1,16 +1,10 @@ -void complex_condition_one(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h, bool i, bool j, - bool k, bool l) { - if (a && b || c && d || e && f || g && h || i && j || k && l) { // $ Alert +void complex_condition(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h, bool i, bool j, + bool k, bool l, bool m, bool n, bool o) { + if (a || b && c || d && e || f && g || h && i || j && k || l && m || n && o) { // $ Alert } } -void complex_condition_two(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h, bool i, bool j, - bool k, bool l, bool m) { - if (a || b && c || d && e || f && g || h && i || j && k || l && m) { // $ Alert - } -} - -void five_logical_operations_is_not_enough(bool a, bool b, bool c, bool d, bool e, bool f) { +void not_complex_condition(bool a, bool b, bool c, bool d, bool e, bool f) { if (a && b || c && d || e && f) { } } diff --git a/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.expected b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.expected index ad7133c60277..fc3d8570dc71 100644 --- a/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.expected +++ b/cpp/ql/test/query-tests/Best Practices/ComplexCondition/ComplexCondition.expected @@ -1,2 +1 @@ -| ComplexCondition.cpp:3:7:3:62 | ... \|\| ... | Complex condition: too many logical operations in this expression. | -| ComplexCondition.cpp:9:7:9:67 | ... \|\| ... | Complex condition: too many logical operations in this expression. | +| ComplexCondition.cpp:3:7:3:77 | ... \|\| ... | Complex condition: too many logical operations in this expression. | diff --git a/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.cpp b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.cpp index cf3bc7d0d4ba..0902ea72ff90 100644 --- a/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.cpp +++ b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.cpp @@ -1,41 +1,25 @@ -void multiple_forward_and_backward_targets_one() { // $ Alert - goto forward_one; - goto forward_two; -forward_one: - ; -forward_two: - ; +bool cond(); + +void multiple_forward_and_backward_goto() { // $ Alert backward_one: - ; + if (cond()) goto forward_one; backward_two: - ; - goto backward_one; - goto backward_two; + if (cond()) goto forward_two; +forward_one: + if (cond()) goto backward_one; +forward_two: + if (cond()) goto backward_two; } -void multiple_forward_and_backward_targets_two() { // $ Alert - goto next_one; - goto next_two; -next_one: - ; -next_two: - ; -earlier_one: - ; -earlier_two: - ; - goto earlier_one; - goto earlier_two; -} +void only_forward_goto() { + if (cond()) goto end; -void one_forward_target_is_not_enough() { - goto forward; -forward: - ; -backward_one: - ; -backward_two: - ; - goto backward_one; - goto backward_two; + // ... + + if (cond()) goto end; + + // ... + +end: + // ... } diff --git a/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.expected b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.expected index f5a4826fbd24..9d4c90b7b389 100644 --- a/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.expected +++ b/cpp/ql/test/query-tests/Best Practices/UseOfGoto/UseOfGoto.expected @@ -1,2 +1 @@ -| UseOfGoto.cpp:1:6:1:46 | definition of multiple_forward_and_backward_targets_one | Multiple forward and backward goto statements may make function multiple_forward_and_backward_targets_one hard to understand. | -| UseOfGoto.cpp:16:6:16:46 | definition of multiple_forward_and_backward_targets_two | Multiple forward and backward goto statements may make function multiple_forward_and_backward_targets_two hard to understand. | +| UseOfGoto.cpp:3:6:3:39 | definition of multiple_forward_and_backward_goto | Multiple forward and backward goto statements may make function multiple_forward_and_backward_goto hard to understand. |