Skip to content

dump-c: sign-extend signed bit-field temporaries#9013

Open
tautschnig wants to merge 1 commit into
diffblue:developfrom
tautschnig:dump-c-bitfield-chained-assign
Open

dump-c: sign-extend signed bit-field temporaries#9013
tautschnig wants to merge 1 commit into
diffblue:developfrom
tautschnig:dump-c-bitfield-chained-assign

Conversation

@tautschnig
Copy link
Copy Markdown
Collaborator

When goto-conversion lowers a chained assignment outer = bf = expr through a bit-field lvalue, it introduces a temporary symbol whose declared type is the bit-field type. goto_program2code rewrites that temporary's type to the bit-field's underlying integer type and previously masked the initialiser with & ((1 << N) - 1) to model the bit-field truncation.

For unsigned bit-fields the AND-mask is enough, but for signed bit-fields the value of bf = expr is the value of bf after the assignment - i.e. the masked value sign-extended to the underlying type (per C11 6.5.16.1p3). Without the sign extension, the temporary held an unsigned-truncated value, so subsequent uses of it (here: the chained assignment to outer) observed the wrong value. The original program continued to verify correctly under CBMC, but the C code emitted by --dump-c no longer agreed with the source - which CSmith picks up as a checksum mismatch.

Apply branchless sign extension ((v & mask) ^ sign_bit) - sign_bit for the signed-and-narrower case. This expression stays within the bit-field's value range and so triggers neither signed overflow nor implementation-defined shift behaviour in the dumped C.

  • Each commit message has a non-empty body, explaining why the change was made.
  • n/a Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • n/a The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • n/a My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • n/a White-space or formatting changes outside the feature-related changed lines are in commits of their own.

When goto-conversion lowers a chained assignment `outer = bf = expr`
through a bit-field lvalue, it introduces a temporary symbol whose
declared type is the bit-field type. `goto_program2code` rewrites that
temporary's type to the bit-field's underlying integer type and
previously masked the initialiser with `& ((1 << N) - 1)` to model the
bit-field truncation.

For unsigned bit-fields the AND-mask is enough, but for signed
bit-fields the value of `bf = expr` is the value of `bf` after the
assignment - i.e. the masked value sign-extended to the underlying type
(per C11 6.5.16.1p3). Without the sign extension, the temporary held
an unsigned-truncated value, so subsequent uses of it (here: the
chained assignment to `outer`) observed the wrong value. The original
program continued to verify correctly under CBMC, but the C code
emitted by `--dump-c` no longer agreed with the source - which CSmith
picks up as a checksum mismatch.

Apply branchless sign extension `((v & mask) ^ sign_bit) - sign_bit`
for the signed-and-narrower case. This expression stays within the
bit-field's value range and so triggers neither signed overflow nor
implementation-defined shift behaviour in the dumped C.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig tautschnig self-assigned this May 25, 2026
Copilot AI review requested due to automatic review settings May 25, 2026 19:01
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes --dump-c output semantics for chained assignments through signed bit-fields by ensuring that temporaries introduced during lowering observe the C-standard-required sign-extended value of the bit-field after assignment (C11 6.5.16.1p3). This aligns dumped C with source behavior and prevents checksum mismatches (e.g., from CSmith) while leaving verification behavior unchanged.

Changes:

  • Update goto_program2code bit-field temporary rewriting to apply branchless sign extension for signed, narrower-than-underlying bit-fields.
  • Keep existing masking behavior for unsigned bit-fields and for signed bit-fields that are not narrower than their underlying type.
  • Add a regression test that exercises outer = s.r = v where s.r is a 2-bit signed bit-field and checks the dumped-C path preserves sign-extension semantics.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/goto-instrument/goto_program2code.cpp Sign-extends masked initializer for signed, narrow bit-field temporaries when rewriting their declared type to the underlying integer type.
regression/goto-instrument/dump-bitfield-chained-assign/test.desc Adds a --dump-c regression test description to ensure dumped C remains verifiable and preserves correct chained-assignment semantics.
regression/goto-instrument/dump-bitfield-chained-assign/main.c Minimal C program reproducing the signed bit-field chained-assignment sign-extension case (2 stored into 2-bit signed bit-field yields -2).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 25, 2026

Codecov Report

❌ Patch coverage is 90.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 80.55%. Comparing base (808dae2) to head (17fdcb6).

Files with missing lines Patch % Lines
src/goto-instrument/goto_program2code.cpp 90.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #9013   +/-   ##
========================================
  Coverage    80.55%   80.55%           
========================================
  Files         1707     1707           
  Lines       189051   189058    +7     
  Branches        73       73           
========================================
+ Hits        152299   152305    +6     
- Misses       36752    36753    +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

2 participants