Skip to content

Fix debug build warnings: uninitialized intent(out) args, unused variables#1340

Closed
sbryngelson wants to merge 11 commits intoMFlowCode:masterfrom
sbryngelson:fix-debug-warnings
Closed

Fix debug build warnings: uninitialized intent(out) args, unused variables#1340
sbryngelson wants to merge 11 commits intoMFlowCode:masterfrom
sbryngelson:fix-debug-warnings

Conversation

@sbryngelson
Copy link
Copy Markdown
Member

Summary

  • Initialize intent(out) arguments unconditionally before #ifdef MFC_SIMULATION blocks to fix "INTENT(OUT) but was not set" warnings in non-simulation builds
  • Change intent(out) to intent(inout) on s_mpi_allreduce_vectors_sum to fix aliasing violation when same array passed as both input and output
  • Remove unused local variables verified across all build targets

CI note

This draft includes a temporary CI step ("Collect Compiler Warnings") that rebuilds each target with -j1 and captures all compiler warnings as artifacts. This is to collect warning lists from gfortran and ifx before making further removals. The CI step will be removed before merging.

Test plan

  • ./mfc.sh precheck -j 8 passes
  • ./mfc.sh build -j 8 passes (gfortran, CPU, MPI)
  • ./mfc.sh test --reldebug -j 8 -% 5 passes (27/27)
  • CI: gfortran (ubuntu) — warnings collected
  • CI: ifx (ubuntu, intel) — warnings collected
  • CI: gfortran (macos) — warnings collected

- m_mpi_common.fpp: Initialize icfl_max_glb/vcfl_max_glb/Rc_min_glb before
  #ifdef MFC_SIMULATION. Use block/end block for ierr declaration to avoid
  declaration-after-executable-statement error.
  Change intent(out) to intent(inout) in s_mpi_allreduce_vectors_sum for
  aliased calls.
- m_variables_conversion.fpp: Initialize rho_K/gamma_K/pi_inf_K/qv_K/Re_K/G_K
  before #ifdef MFC_SIMULATION in s_convert_species_to_mixture_variables_acc.
@sbryngelson sbryngelson marked this pull request as ready for review March 31, 2026 18:28
@github-actions
Copy link
Copy Markdown

Claude Code Review

Head SHA: d792134

Files changed:

  • 15
  • .github/workflows/test.yml
  • CMakeLists.txt
  • src/common/m_helper.fpp
  • src/common/m_mpi_common.fpp
  • src/common/m_variables_conversion.fpp
  • src/post_process/m_data_output.fpp
  • src/pre_process/m_icpp_patches.fpp
  • src/simulation/m_bubbles_EL.fpp
  • src/simulation/m_compute_cbc.fpp
  • src/simulation/m_compute_levelset.fpp

Findings:

  • src/common/m_mpi_common.fpps_mpi_allreduce_vectors_sum: incomplete non-MPI fallback after intent change. var_glb was changed from intent(out) to intent(inout), but the diff shows no corresponding #else (non-MPI) assignment var_glb = var_loc being added. In a non-MPI build MPI_Allreduce is never called, so var_glb is never written — callers who historically relied on intent(out) semantics and passed an uninitialized array will now silently receive back their uninitialized input rather than the correct single-rank value. Compare with s_mpi_reduce_cfl in the same diff, which correctly pre-initializes its outputs unconditionally before the #ifdef MFC_MPI block. The same pattern (var_glb = var_loc in the #else path) is needed here.

  • CMakeLists.txtRelDebug NVHPC target gains -gpu=debug via the broadened OR condition. MFC_SETUP_TARGET now emits -gpu=debug for both Debug and RelDebug build types (the OR at line 635). For NVHPC's RelDebug block the compile options already include -O1. Combining -gpu=debug (device-side instrumentation) with -O1 can interfere with GPU kernel optimisation and is not the intended "lightweight debug" behaviour. The Debug build already uses -O0 where -gpu=debug is expected; for RelDebug it should probably be omitted or restricted to Debug only.

  • .github/workflows/test.yml — Warning-collection step serially re-compiles every target after tests, significantly extending CI wall-time. The new Collect Compiler Warnings step touches all pre-processed .f90 files (find fypp/ -name '*.f90' -exec touch {} +) and then re-runs make "$target" -j1 for each staging directory. A single-threaded full-target recompile on, e.g., the simulation target can be as expensive as the original build. If warning surfacing is the goal, capturing the build output during the original ./mfc.sh build invocation (e.g. with tee) avoids the re-compilation entirely.

@github-actions
Copy link
Copy Markdown

Claude Code Review

Head SHA: 1eaee91

Files changed:

  • 15
  • .github/workflows/test.yml
  • CMakeLists.txt
  • src/common/m_helper.fpp
  • src/common/m_mpi_common.fpp
  • src/common/m_variables_conversion.fpp
  • src/post_process/m_data_output.fpp
  • src/pre_process/m_icpp_patches.fpp
  • src/simulation/m_bubbles_EL.fpp
  • src/simulation/m_compute_cbc.fpp
  • src/simulation/m_compute_levelset.fpp

Findings:

  • s_mpi_allreduce_vectors_sum: non-MPI builds leave var_glb unassigned (src/common/m_mpi_common.fpp). The intent was changed from intent(out) to intent(inout) to silence the uninitialized-variable warning introduced by -finit-real=snan. However, in non-MPI builds the entire #ifdef MFC_MPI block is absent and var_glb is never written. A caller in a non-MPI build will read back whatever value it passed in (or sNaN-initialized garbage), not the local sum. The correct fix is to add var_glb = var_loc in the non-MPI path, analogous to the scalar reduction fix applied in the same file to s_mpi_reduce_cfl_variables where icfl_max_glb = icfl_max_loc etc. are assigned unconditionally before the #ifdef MFC_MPI block.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 31, 2026

Claude Code Review

Incremental review from: 6439d2f
Head SHA: 0415ca1

New findings since last Claude review:

  • collect-warnings.sh: echo separator lines will fail ./mfc.sh precheck.
    Lines 7, 15, 27 contain echo "=== Collecting compiler warnings ===", echo "=== Target: $target ===", and echo "=== Done collecting warnings ===". Per project lint rules for .github/ shell scripts, === echo separators longer than 20 characters must be shortened or removed. This file sits under .github/workflows/common/ which is in the scanned path, so these lines will fail the CI lint gate.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 31, 2026

Claude Code Review

Incremental review from: 4fff2da
Head SHA: 9574365

New findings since last Claude review:

  • Test step removed from github job — regression tests no longer run on Ubuntu/macOS CI. The github job previously had two steps: a Build step using --dry-run (compile-only) and a separate Test step that ran mfc.sh test -v --max-attempts 3. The diff removes the Test step entirely (the hunk starting at line 113 in the original). The remaining Build step uses --dry-run which only compiles, it does not execute any test cases. PRs no longer receive regression test coverage from the Ubuntu/macOS matrix.

  • lint-gate job entirely removed — CI no longer enforces code quality checks. The diff removes the complete lint-gate job which ran formatting checks, spell checking, ./mfc.sh lint, lint_source.py, lint_docs.py, and lint_param_docs.py. CLAUDE.md states these six checks are the CI lint gate and that ./mfc.sh precheck must pass before every commit. With lint-gate gone and needs: [lint-gate, ...] removed from both github and self, none of these checks run in CI and they no longer block job execution.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a new RelDebug build type alongside existing Debug and Release modes, adds automated compiler warning collection to the CI pipeline, and performs code cleanup by removing unused variables. The RelDebug configuration applies lightweight debug instrumentation with partial optimizations (e.g., -Og, -O1 depending on compiler) and sets -g for debugging symbols. A new Bash script collects warnings from CMake-built targets by forcing recompilation and filtering compiler output. The GitHub Actions workflow integrates warning collection and reporting as artifacts. CLI toolchain updates support the new build mode configuration.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title directly summarizes the main changes: fixing debug build warnings from uninitialized intent(out) arguments and removing unused variables.
Description check ✅ Passed The PR description is mostly complete with a clear summary section, test plan, and CI notes. It covers the key changes, though the description template asks for a 'Testing' section that is not fully addressed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
.github/workflows/test.yml (2)

264-281: Please route the GitHub job through the shared warning collector.

This is already a second implementation of the same collector, and it has drifted from .github/workflows/common/collect-warnings.sh (-B2 here vs -B3 there, /tmp/warnings_*.txt only on this path). If you move the file-writing into the shared script and call it here, fixes to the warning logic only need to land once.


302-308: Please confirm dropping the draft guard is intentional.

Removing github.event.pull_request.draft != true means the Phoenix/Frontier matrix will now run on every draft PR update as well. Since case-optimization below is still draft-gated, this looks easy to do accidentally and can burn a lot of queue time if it was not deliberate.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3e48f2af-f7ba-41d4-a254-11482fc3b634

📥 Commits

Reviewing files that changed from the base of the PR and between afc724e and 6439d2f.

📒 Files selected for processing (16)
  • .github/workflows/common/collect-warnings.sh
  • .github/workflows/test.yml
  • CMakeLists.txt
  • src/common/m_helper.fpp
  • src/common/m_mpi_common.fpp
  • src/common/m_variables_conversion.fpp
  • src/post_process/m_data_output.fpp
  • src/pre_process/m_icpp_patches.fpp
  • src/simulation/m_bubbles_EL.fpp
  • src/simulation/m_compute_cbc.fpp
  • src/simulation/m_compute_levelset.fpp
  • src/simulation/m_start_up.fpp
  • toolchain/mfc/build.py
  • toolchain/mfc/cli/argparse_gen.py
  • toolchain/mfc/cli/docs_gen.py
  • toolchain/mfc/state.py
💤 Files with no reviewable changes (1)
  • src/simulation/m_compute_cbc.fpp

Comment on lines +18 to +21
# Touch all generated .f90 to force recompile
find fypp/ -name '*.f90' -exec touch {} + 2>/dev/null
# Rebuild single-threaded to get clean warning output with file/line context
make "$target" -j1 2>&1 | grep -E "Warning:|warning:" -B3 || echo "(no warnings)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check the script for pipefail and understand its context
cat -n .github/workflows/common/collect-warnings.sh | head -30

Repository: MFlowCode/MFC

Length of output: 1243


🏁 Script executed:

# Look for HANDLE_SOURCES in CMakeLists.txt
rg -A 10 "HANDLE_SOURCES" --type cmake

Repository: MFlowCode/MFC

Length of output: 2254


🏁 Script executed:

# Check if there are any checked-in .f90 files (not generated)
find . -name "*.f90" -type f | grep -v fypp | grep -v build | head -20

Repository: MFlowCode/MFC

Length of output: 330


🏁 Script executed:

# Understand the build directory structure and where fypp outputs go
find . -name "CMakeLists.txt" -type f | head -5

Repository: MFlowCode/MFC

Length of output: 113


🏁 Script executed:

# Check how other workflows/scripts rebuild targets
rg "cmake --build|make.*target" --type bash

Repository: MFlowCode/MFC

Length of output: 85


🏁 Script executed:

# Look at how mfc.sh handles test/build operations
head -100 ./mfc.sh

Repository: MFlowCode/MFC

Length of output: 3461


🏁 Script executed:

# Check if there's existing warning collection or CI logic
rg -A 5 "collect-warnings" .github/workflows/

Repository: MFlowCode/MFC

Length of output: 902


Use cmake --build with --clean-first instead of selective touch + make | grep.

This script touches only generated .f90 files in fypp/, but HANDLE_SOURCES in CMakeLists.txt compiles both generated and checked-in .f90 sources (e.g., src/common/m_compile_specific.f90). Checked-in files retain their original timestamps and won't be recompiled in the rebuild, so their warnings never reappear. Also, under set -o pipefail (line 5), a failing make triggers the || echo "(no warnings)" fallback, masking build failures as clean runs. A cmake --build . --target "$target" --parallel 1 --clean-first with proper error handling avoids both problems.

🛠️ Suggested change
-    # Touch all generated .f90 to force recompile
-    find fypp/ -name '*.f90' -exec touch {} + 2>/dev/null
-    # Rebuild single-threaded to get clean warning output with file/line context
-    make "$target" -j1 2>&1 | grep -E "Warning:|warning:" -B3 || echo "(no warnings)"
+    tmp_log=$(mktemp)
+    if ! cmake --build . --target "$target" --parallel 1 --clean-first >"$tmp_log" 2>&1; then
+        echo "(warning collection rebuild failed)"
+        cat "$tmp_log"
+    else
+        grep -E "Warning:|warning:" -B3 "$tmp_log" || echo "(no warnings)"
+    fi
+    rm -f "$tmp_log"

Comment on lines +344 to +346
integer, intent(in) :: num_vectors, vector_length
real(wp), dimension(:,:), intent(in) :: var_loc
real(wp), dimension(:,:), intent(inout) :: var_glb
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python - <<'PY'
from pathlib import Path
import re

pat = re.compile(r'call\s+s_mpi_allreduce_vectors_sum\s*\(', re.I)

for pattern in ("*.fpp", "*.f90"):
    for path in Path("src").rglob(pattern):
        text = path.read_text(encoding="utf-8", errors="ignore")
        idx = 0

        while True:
            m = pat.search(text, idx)
            if not m:
                break

            i = m.end()
            depth = 1
            while i < len(text) and depth:
                if text[i] == '(':
                    depth += 1
                elif text[i] == ')':
                    depth -= 1
                i += 1

            call = text[m.start():i]
            args = re.sub(r'&\s*\n\s*&?', ' ', call[call.find('(') + 1:-1])

            parts, cur, depth = [], [], 0
            for ch in args:
                if ch == '(':
                    depth += 1
                elif ch == ')':
                    depth -= 1
                if ch == ',' and depth == 0:
                    parts.append(''.join(cur).strip())
                    cur = []
                else:
                    cur.append(ch)
            parts.append(''.join(cur).strip())

            if len(parts) >= 2 and parts[0].lower() == parts[1].lower():
                line = text.count('\n', 0, m.start()) + 1
                print(f"{path}:{line}: {parts[0]}")

            idx = i
PY

Repository: MFlowCode/MFC

Length of output: 133


🏁 Script executed:

head -346 src/common/m_mpi_common.fpp | tail -10

Repository: MFlowCode/MFC

Length of output: 474


🏁 Script executed:

sed -n '340,350p' src/common/m_mpi_common.fpp

Repository: MFlowCode/MFC

Length of output: 524


🏁 Script executed:

sed -n '1000,1015p' src/simulation/m_ibm.fpp

Repository: MFlowCode/MFC

Length of output: 610


🏁 Script executed:

sed -n '344,380p' src/common/m_mpi_common.fpp

Repository: MFlowCode/MFC

Length of output: 1447


Split the in-place and two-buffer allreduce APIs.

Passing the same actual array as both intent(in) (var_loc) and intent(inout) (var_glb) arguments violates Fortran standard conformance constraints at the interface level. Although the implementation includes a runtime check using loc() and MPI_IN_PLACE, this does not resolve the constraint violation—different compilers may reject, warn, or silently mishandle this pattern. Per the coding guidelines, all code must compile with GNU gfortran, NVIDIA nvfortran, Cray ftn, and Intel ifx compilers.

The codebase currently has two call sites with this issue:

  • src/simulation/m_ibm.fpp:1007: call s_mpi_allreduce_vectors_sum(forces, forces, num_ibs, 3)
  • src/simulation/m_ibm.fpp:1008: call s_mpi_allreduce_vectors_sum(torques, torques, num_ibs, 3)

Use a dedicated in-place entry point or a generic overload to separate the two-buffer API from the in-place API.

real(wp) :: normals(1:3) !< Boundary normal buffer
integer :: boundary_vertex_count, boundary_edge_count, total_vertices !< Boundary vertex
real(wp) :: normals(1:3) !< Boundary normal buffer
integer :: boundary_vertex_count, boundary_edge_count, total_vertices !< Boundary vertex
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove still-unused total_vertices from s_icpp_model.

Line 1272 declares total_vertices, but it is not used later in the routine, so this likely keeps an unused-local warning alive.

Suggested diff
-        integer                                 :: boundary_vertex_count, boundary_edge_count, total_vertices  !< Boundary vertex
+        integer                                 :: boundary_vertex_count, boundary_edge_count  !< Boundary vertex
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
integer :: boundary_vertex_count, boundary_edge_count, total_vertices !< Boundary vertex
integer :: boundary_vertex_count, boundary_edge_count !< Boundary vertex

mpi: bool = True
gpu: str = gpuConfigOptions.NONE.value
debug: bool = False
reldebug: bool = False
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

reldebug shouldn't be another independent boolean.

Line 18 makes debug=true, reldebug=true a valid config. toolchain/mfc/build.py then silently collapses that to Debug, while make_slug() and make_options() still preserve both flags, so one effective build mode can hash to multiple staging dirs. Please enforce mutual exclusivity or model build type as a single field.

Comment on lines +47 to +51
cli_k = k.replace("_", "-")
if k == "gpu":
options.append(f"--{v}-{k}")
options.append(f"--{v}-{cli_k}")
else:
options.append(f"--{'no-' if not v else ''}{k}")
options.append(f"--{'no-' if not v else ''}{cli_k}")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

make_options() now emits a GPU flag the parser doesn't accept.

For gpu="acc" or gpu="mp", this returns --acc-gpu / --mp-gpu, but _add_mfc_config_arguments() only defines --gpu [acc/mp] and --no-gpu. Any round-trip that reconstructs CLI args from MFCConfig will break on GPU configs.

🛠️ Suggested change
         for k, v in self.items():
             cli_k = k.replace("_", "-")
             if k == "gpu":
-                options.append(f"--{v}-{cli_k}")
+                if v == gpuConfigOptions.NONE.value:
+                    options.append(f"--no-{cli_k}")
+                else:
+                    options.append(f"--{cli_k}={v}")
             else:
                 options.append(f"--{'no-' if not v else ''}{cli_k}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cli_k = k.replace("_", "-")
if k == "gpu":
options.append(f"--{v}-{k}")
options.append(f"--{v}-{cli_k}")
else:
options.append(f"--{'no-' if not v else ''}{k}")
options.append(f"--{'no-' if not v else ''}{cli_k}")
cli_k = k.replace("_", "-")
if k == "gpu":
if v == gpuConfigOptions.NONE.value:
options.append(f"--no-{cli_k}")
else:
options.append(f"--{cli_k}={v}")
else:
options.append(f"--{'no-' if not v else ''}{cli_k}")

@sbryngelson sbryngelson mentioned this pull request Mar 31, 2026
5 tasks
@sbryngelson sbryngelson force-pushed the fix-debug-warnings branch 3 times, most recently from 4356909 to a9ffd4e Compare March 31, 2026 20:41
Build self-hosted targets with --reldebug to enable warning flags.
Skip test step on self-hosted (only need build output for warnings).
Skip rebuild-cache entirely (not needed for warning collection).

Add compile-time warning flags to RelDebug for all compilers:
- Cray ftn: -h msgs -h msglevel_0 -h style
- LLVMFlang: -Wall -Wextra -Wunused
- Intel ifx: -warn all
- NVHPC: -Minform=inform -Mstandard
This CI change is temporary and will be reverted before merge.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant