From cde4c2348c441dd1b8f37777ca74f000760ba6cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20G=2E=20Dieste?= Date: Thu, 5 Feb 2026 18:31:06 +0100 Subject: [PATCH 1/2] PWR082: Add entry and code examples --- Checks/PWR082/README.md | 132 +++++++++++++++++++++++++++++++++++++ Checks/PWR082/example.c | 11 ++++ Checks/PWR082/example.f90 | 13 ++++ Checks/PWR082/solution.c | 11 ++++ Checks/PWR082/solution.f90 | 13 ++++ README.md | 1 + 6 files changed, 181 insertions(+) create mode 100644 Checks/PWR082/README.md create mode 100644 Checks/PWR082/example.c create mode 100644 Checks/PWR082/example.f90 create mode 100644 Checks/PWR082/solution.c create mode 100644 Checks/PWR082/solution.f90 diff --git a/Checks/PWR082/README.md b/Checks/PWR082/README.md new file mode 100644 index 0000000..bf244b4 --- /dev/null +++ b/Checks/PWR082/README.md @@ -0,0 +1,132 @@ +# PWR082: Remove unused variables + +### Issue + +A variable that is declared but never used adds noise: it increases the amount +of information to keep track of, suggesting data flow that does not actually +exist. In some cases, an unused variable may instead hint at a hidden defect in +the program's logic, such as a missing assignment or an incomplete computation. + +### Actions + +Determine whether each unused variable is accidentally or intentionally unused; +remove those that are not needed. If a variable is intentionally unused but, +for any reason, it cannot be removed, make that intent explicit using +language-specific mechanisms. + +### Relevance + +Fortran, C, and C++ allow variables to be declared without ever being used. +Eliminating unused variables reduces cognitive load and avoids suggesting +nonexistent data flow, helping readers focus on what actually contributes to +the program's behavior. + +If a variable `x` must remain intentionally unused (e.g., an argument required +in an API call but unused in a particular implementation), it is possible to +document that intent using language constructs, such as: + +- **C:** `[[maybe_unused]] int x` (since C23), or compiler-specific annotations + such as `gcc`'s `__attribute__((unused))`. Another common alternative, + although less explicit, is to "consume" the variable with a cast `(void) x`. + +- **C++:** `[[maybe_unused]] int x` (since C++17). + +- **Fortran:** There is no standard attribute, and compilers such as `gfortran` + do not provide attributes for annotation. A simple and portable approach is + to create a reference with no runtime effect: + +```fortran +associate(unused => x) +end associate +``` + +### Code examples + +#### C + +In the following code, the variable `t` is declared but never used to perform +the computation: + +```c {3} showLineNumbers +// example.c +__attribute__((pure)) int sumArray(const int n, const int *array) { + int t, sum = 0; + + for (int i = 0; i < n; ++i) { + sum += array[i]; + } + + return sum; +} +``` + +Thus, `t` should be removed: + +```c {3} showLineNumbers +// solution.c +__attribute__((pure)) int sumArray(const int n, const int *array) { + int sum = 0; + + for (int i = 0; i < n; ++i) { + sum += array[i]; + } + + return sum; +} +``` + +#### Fortran + +In the following code, the variable `t` is declared but never used to perform +the computation: + +```fortran {5} showLineNumbers +! example.f90 +pure function sumArray(array) result(sum) + implicit none + integer, intent(in) :: array(:) + integer :: t, sum, i + + sum = 0 + + do i = 1, size(array) + sum = sum + array(i) + end do +end function sumArray +``` + +Thus, `t` should be removed: + +```fortran {5} showLineNumbers +! solution.f90 +pure function sumArray(array) result(sum) + implicit none + integer, intent(in) :: array(:) + integer :: sum, i + + sum = 0 + + do i = 1, size(array) + sum = sum + array(i) + end do +end function sumArray +``` + +### Related resources + +- [PWR082 + examples](https://github.com/codee-com/open-catalog/tree/main/Checks/PWR082/) + +### References + +- ["Common Variable Attributes (Using the GNU Compiler Collection + (GCC))"](https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-unused-variable-attribute), + Free Software Foundation, Inc. [last checked February 2026] + +- ["C attribute: maybe_unused (since + C23)"](https://en.cppreference.com/w/c/language/attributes/maybe_unused.html), + cppreference.com. [last checked February 2026] + +- ["C++ attribute: maybe_unused (since + C++17)"](https://en.cppreference.com/w/cpp/language/attributes/maybe_unused.html), + cppreference.com. [last checked February 2026] diff --git a/Checks/PWR082/example.c b/Checks/PWR082/example.c new file mode 100644 index 0000000..c56982c --- /dev/null +++ b/Checks/PWR082/example.c @@ -0,0 +1,11 @@ +// PWR082: Remove unused variables + +__attribute__((pure)) int sumArray(const int n, const int *array) { + int t, sum = 0; + + for (int i = 0; i < n; ++i) { + sum += array[i]; + } + + return sum; +} diff --git a/Checks/PWR082/example.f90 b/Checks/PWR082/example.f90 new file mode 100644 index 0000000..4fd4ef0 --- /dev/null +++ b/Checks/PWR082/example.f90 @@ -0,0 +1,13 @@ +! PWR082: Remove unused variables + +pure function sumArray(array) result(sum) + implicit none + integer, intent(in) :: array(:) + integer :: t, sum, i + + sum = 0 + + do i = 1, size(array) + sum = sum + array(i) + end do +end function sumArray diff --git a/Checks/PWR082/solution.c b/Checks/PWR082/solution.c new file mode 100644 index 0000000..f205901 --- /dev/null +++ b/Checks/PWR082/solution.c @@ -0,0 +1,11 @@ +// PWR082: Remove unused variables + +__attribute__((pure)) int sumArray(const int n, const int *array) { + int sum = 0; + + for (int i = 0; i < n; ++i) { + sum += array[i]; + } + + return sum; +} diff --git a/Checks/PWR082/solution.f90 b/Checks/PWR082/solution.f90 new file mode 100644 index 0000000..8792f6e --- /dev/null +++ b/Checks/PWR082/solution.f90 @@ -0,0 +1,13 @@ +! PWR082: Remove unused variables + +pure function sumArray(array) result(sum) + implicit none + integer, intent(in) :: array(:) + integer :: sum, i + + sum = 0 + + do i = 1, size(array) + sum = sum + array(i) + end do +end function sumArray diff --git a/README.md b/README.md index fd6fe2a..5732f49 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ designed to demonstrate: | [PWR079](Checks/PWR079/) | Avoid undefined behavior due to uninitialized variables | correctness, portability, security | [CWE-758](https://cwe.mitre.org/data/definitions/758.html), [CWE-908](https://cwe.mitre.org/data/definitions/908.html), [CWE-909](https://cwe.mitre.org/data/definitions/909.html) | [6.13](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.22](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.56](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP33-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+not+read+uninitialized+memory), [EXP34-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers), [MSC15-C](https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior) | [EXP53-CPP](https://wiki.sei.cmu.edu/confluence/spaces/cplusplus/pages/88046609/EXP53-CPP.+Do+not+read+uninitialized+memory) | ✓ | ✓ | ✓ | | | [PWR080](Checks/PWR080/) | Conditionally initialized variables can lead to undefined behavior | correctness, portability, security | [CWE-758](https://cwe.mitre.org/data/definitions/758.html), [CWE-908](https://cwe.mitre.org/data/definitions/908.html), [CWE-909](https://cwe.mitre.org/data/definitions/909.html) | [6.13](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.22](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.56](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP33-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+not+read+uninitialized+memory), [EXP34-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers), [MSC15-C](https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior) | [EXP53-CPP](https://wiki.sei.cmu.edu/confluence/spaces/cplusplus/pages/88046609/EXP53-CPP.+Do+not+read+uninitialized+memory) | ✓ | ✓ | ✓ | | | [PWR081](Checks/PWR081/) | Uninitialized output arguments can lead to undefined behavior | correctness, portability, security | [CWE-758](https://cwe.mitre.org/data/definitions/758.html), [CWE-908](https://cwe.mitre.org/data/definitions/908.html), [CWE-909](https://cwe.mitre.org/data/definitions/909.html) | [6.13](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.22](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.56](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP33-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+not+read+uninitialized+memory), [EXP34-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers), [MSC15-C](https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior) | | | ✓ | | | +| [PWR082](Checks/PWR082/) | Remove unused variables | correctness, security | [CWE-563](https://cwe.mitre.org/data/definitions/563.html) | [6.19](https://j3-fortran.org/doc/year/23/23-241.pdf) | [MSC13-C](https://wiki.sei.cmu.edu/confluence/spaces/c/pages/87152095/MSC13-C.+Detect+and+remove+unused+values) | | ✓ | ✓ | ✓ | | | [PWR083](Checks/PWR083/) | Match the types of dummy and actual arguments in procedure calls | correctness, security | [CWE-628](https://cwe.mitre.org/data/definitions/628.html), [CWE-758](https://cwe.mitre.org/data/definitions/758.html) | [6.11](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.32](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.53](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.56](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP37-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP37-C.+Call+functions+with+the+correct+number+and+type+of+arguments), [MSC15-C](https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior) | | | ✓ | | | | [PWR088](Checks/PWR088/) | Add missing arguments to procedure calls | correctness, security | [CWE-628](https://cwe.mitre.org/data/definitions/628.html), [CWE-758](https://cwe.mitre.org/data/definitions/758.html) | [6.32](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.56](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP37-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP37-C.+Call+functions+with+the+correct+number+and+type+of+arguments), [MSC15-C](https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior) | | | ✓ | | | | [PWR089](Checks/PWR089/) | Remove unexpected arguments from procedure calls | correctness, security | [CWE-628](https://cwe.mitre.org/data/definitions/628.html), [CWE-758](https://cwe.mitre.org/data/definitions/758.html) | [6.32](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.56](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP37-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP37-C.+Call+functions+with+the+correct+number+and+type+of+arguments), [MSC15-C](https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior) | | | ✓ | | | From 4e160215fed5d533fc3d11ce30a8cb365728e25d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20G=2E=20Dieste?= Date: Fri, 6 Feb 2026 12:23:03 +0100 Subject: [PATCH 2/2] PWR082: Add benchmark --- Benchmark/src/CMakeLists.txt | 1 + Benchmark/src/PWR082.cpp | 66 ++++++++++++++++++++++++++++ Checks/PWR082/benchmark/example.c | 11 +++++ Checks/PWR082/benchmark/example.f90 | 18 ++++++++ Checks/PWR082/benchmark/solution.c | 12 +++++ Checks/PWR082/benchmark/solution.f90 | 18 ++++++++ 6 files changed, 126 insertions(+) create mode 100644 Benchmark/src/PWR082.cpp create mode 100644 Checks/PWR082/benchmark/example.c create mode 100644 Checks/PWR082/benchmark/example.f90 create mode 100644 Checks/PWR082/benchmark/solution.c create mode 100644 Checks/PWR082/benchmark/solution.f90 diff --git a/Benchmark/src/CMakeLists.txt b/Benchmark/src/CMakeLists.txt index 7e1f266..9f2a35a 100644 --- a/Benchmark/src/CMakeLists.txt +++ b/Benchmark/src/CMakeLists.txt @@ -21,4 +21,5 @@ endif() add_benchmark(PWR079) add_benchmark(PWR080) add_benchmark(PWR081) +add_benchmark(PWR082) add_benchmark(PWR083) diff --git a/Benchmark/src/PWR082.cpp b/Benchmark/src/PWR082.cpp new file mode 100644 index 0000000..2abf39a --- /dev/null +++ b/Benchmark/src/PWR082.cpp @@ -0,0 +1,66 @@ +#include "Benchmark.h" + +// Forward-declare the functions to benchmark +extern "C" { +double sum_array(const int n, const double *array); +double sum_array_improved(const int n, const double *array); +double sum_array_f(const int n, const double *array); +double sum_array_improved_f(const int n, const double *array); +} + +// Size adjusted to fit execution on micro-seconds +constexpr int N = 1024 * 1024; + +#if OCB_ENABLE_C + +static void CExampleBench(benchmark::State &state) { + auto array = OpenCatalog::CreateRandomVector(N); + + for (auto _ : state) { + double result = sum_array(N, array.data()); + benchmark::DoNotOptimize(result); + } +} + +static void CImprovedBench(benchmark::State &state) { + auto array = OpenCatalog::CreateRandomVector(N); + + for (auto _ : state) { + double result = sum_array_improved(N, array.data()); + benchmark::DoNotOptimize(result); + } +} + +// The goal of these benchmarks is to demonstrate that the suggested check does +// not incur any performance penalty +OC_BENCHMARK("PWR082 C Example", CExampleBench); +OC_BENCHMARK("PWR082 C Improved", CImprovedBench); + +#endif + +#if OCB_ENABLE_Fortran + +static void FortranExampleBench(benchmark::State &state) { + auto array = OpenCatalog::CreateRandomVector(N); + + for (auto _ : state) { + double result = sum_array_f(N, array.data()); + benchmark::DoNotOptimize(result); + } +} + +static void FortranImprovedBench(benchmark::State &state) { + auto array = OpenCatalog::CreateRandomVector(N); + + for (auto _ : state) { + double result = sum_array_improved_f(N, array.data()); + benchmark::DoNotOptimize(result); + } +} + +// The goal of these benchmarks is to demonstrate that the suggested check does +// not incur any performance penalty +OC_BENCHMARK("PWR082 Fortran Example", FortranExampleBench); +OC_BENCHMARK("PWR082 Fortran Improved", FortranImprovedBench); + +#endif diff --git a/Checks/PWR082/benchmark/example.c b/Checks/PWR082/benchmark/example.c new file mode 100644 index 0000000..2926009 --- /dev/null +++ b/Checks/PWR082/benchmark/example.c @@ -0,0 +1,11 @@ +// PWR082: Remove unused variables + +__attribute__((pure)) double sum_array(const int n, const double *array) { + double t, sum = 0.0; + + for (int i = 0; i < n; ++i) { + sum += array[i]; + } + + return sum; +} diff --git a/Checks/PWR082/benchmark/example.f90 b/Checks/PWR082/benchmark/example.f90 new file mode 100644 index 0000000..1b6ab4d --- /dev/null +++ b/Checks/PWR082/benchmark/example.f90 @@ -0,0 +1,18 @@ +! PWR082: Remove unused variables + +! NOT-PWR070: Explicit-shape arrays used for C-interoperability +pure function sum_array_f(n, array) result(sum) bind(c) + use iso_c_binding, only: c_double, c_int + implicit none + + integer(kind=c_int), intent(in), value :: n + real(kind=c_double), dimension(n), intent(in) :: array + real(kind=c_double) :: t, sum + integer(kind=c_int) :: i + + sum = 0 + + do i = 1, n + sum = sum + array(i) + end do +end function sum_array_f diff --git a/Checks/PWR082/benchmark/solution.c b/Checks/PWR082/benchmark/solution.c new file mode 100644 index 0000000..4dd3c2f --- /dev/null +++ b/Checks/PWR082/benchmark/solution.c @@ -0,0 +1,12 @@ +// PWR082: Remove unused variables + +__attribute__((pure)) double sum_array_improved(const int n, + const double *array) { + double sum = 0.0; + + for (int i = 0; i < n; ++i) { + sum += array[i]; + } + + return sum; +} diff --git a/Checks/PWR082/benchmark/solution.f90 b/Checks/PWR082/benchmark/solution.f90 new file mode 100644 index 0000000..38d2e36 --- /dev/null +++ b/Checks/PWR082/benchmark/solution.f90 @@ -0,0 +1,18 @@ +! PWR082: Remove unused variables + +! NOT-PWR070: Explicit-shape arrays used for C-interoperability +pure function sum_array_improved_f(n, array) result(sum) bind(c) + use iso_c_binding, only: c_double, c_int + implicit none + + integer(kind=c_int), intent(in), value :: n + real(kind=c_double), dimension(n), intent(in) :: array + real(kind=c_double) :: sum + integer(kind=c_int) :: i + + sum = 0 + + do i = 1, n + sum = sum + array(i) + end do +end function sum_array_improved_f