Skip to content

fix(validation): reject FB-level VAR_TEMP referenced from a METHOD#1746

Open
ghaith wants to merge 1 commit into
masterfrom
fix/fb-var-temp-from-method
Open

fix(validation): reject FB-level VAR_TEMP referenced from a METHOD#1746
ghaith wants to merge 1 commit into
masterfrom
fix/fb-var-temp-from-method

Conversation

@ghaith
Copy link
Copy Markdown
Collaborator

@ghaith ghaith commented May 19, 2026

Fixes #1745.

Summary

  • A VAR_TEMP declared on a FUNCTION_BLOCK was silently miscompiled
    when read from one of that FB's METHODs: the method allocated its
    own uninitialized stack slot for the temp, the load was undef,
    and any boolean expression depending on it folded to nonsense at
    optimization levels above none.
  • CODESYS rejects the same source ("unresolved reference"), so this PR
    aligns behavior: the resolver no longer leaks a method's enclosing
    VAR_TEMP into the method body, and the validator emits a focused
    diagnostic (E137) instead of the generic "unresolved reference".
  • ACTIONs continue to see the FB's VAR_TEMP because they share the
    FB body's stack frame.

Changes

  • src/index.rsfind_local_member_recursive filters is_temp()
    when crossing from a METHOD into its enclosing POU.
  • src/validation/statement.rsfb_temp_referenced_from_method
    helper emits E137 with a secondary location at the TEMP declaration,
    shadowing the generic unresolved-reference diagnostic for this case.
  • compiler/plc_diagnostics/src/diagnostics/{diagnostics_registry.rs,error_codes/E137.md}
    — register and document E137 with both fix options (promote to
    instance member, or move the TEMP into the method).

Test plan

  • cargo test --workspace — all green, no regressions.
  • cargo fmt --all and cargo clippy --workspace -- -Dwarnings
    — clean.
  • New validator unit tests (inline snapshots):
    • method reading FB-level VAR_TEMP → E137 with secondary location.
    • FB body + ACTION reading the same TEMP → clean.
  • Manual: plc --ir on the reproducer from FB-level VAR_TEMP referenced from a METHOD lowers to an uninitialized method-local #1745 now aborts with
    E137 and emits no IR (previously it produced an undef load).

A method has its own stack frame, so a VAR_TEMP declared on the enclosing
FUNCTION_BLOCK is not accessible. Previously the resolver let the reference
through and codegen emitted a fresh, uninitialized stack slot — the load
was undef and any boolean expression depending on it folded to nonsense at
optimization levels above none.

Now the resolver filters VAR_TEMP when crossing from a METHOD into its
enclosing POU, and the validator emits a focused E137 diagnostic pointing
at the offending read site and the TEMP declaration. ACTIONs continue to
see the TEMP since they share the FB's frame.

Refs #1745

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 19, 2026

Build Artifacts

🐧 Linux

Artifact Link Size
deb-x86_64 Download 38.5 MB
schema Download 0.0 MB
stdlib Download 32.4 MB
plc-x86_64 Download 43.6 MB
deb-aarch64 Download 30.9 MB
plc-aarch64 Download 43.5 MB

From workflow run

🪟 Windows

Artifact Link Size
stdlib.lib Download 4.3 MB
stdlib.dll Download 0.1 MB
plc.exe Download 38.5 MB

From workflow run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FB-level VAR_TEMP referenced from a METHOD lowers to an uninitialized method-local

1 participant