Skip to content

cprover: state-encoding for uninterpreted functions and member/index lvalues#9069

Open
tautschnig wants to merge 2 commits into
diffblue:developfrom
tautschnig:strata/cprover-state-encoding
Open

cprover: state-encoding for uninterpreted functions and member/index lvalues#9069
tautschnig wants to merge 2 commits into
diffblue:developfrom
tautschnig:strata/cprover-state-encoding

Conversation

@tautschnig

@tautschnig tautschnig commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Leave mathematical-function (uninterpreted function) symbols unencoded as state variables, and follow member/index chains to the addressable base expression when state-encoding lvalues.

  • Each commit message has a non-empty body, explaining why the change was made.
  • 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.

@tautschnig tautschnig self-assigned this Jun 18, 2026
Copilot AI review requested due to automatic review settings June 18, 2026 21:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Updates state encoding to better handle uninterpreted (mathematical) function symbols and lvalue member/index chains, and adjusts SMT2 conversion behavior.

Changes:

  • Enable datatype support in the SMT2 state-encoding target.
  • Avoid state-encoding pure mathematical-function symbols; refine member/index handling to only use address-based evaluation when the base is addressable.
  • Avoid splitting struct-tag assignments when RHS is a computed full-struct value (function application / if-then-else).

Reviewed changes

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

File Description
src/cprover/state_encoding_targets.h Enables SMT2 datatypes in the state-encoding converter.
src/cprover/state_encoding_targets.cpp Changes pointer-related size conversion to fall back when size_of_expr fails.
src/cprover/state_encoding.cpp Adjusts expression evaluation and struct assignment splitting to accommodate uninterpreted functions / computed structs.

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

Comment thread src/cprover/state_encoding_targets.cpp Outdated
Comment thread src/cprover/state_encoding_targets.h
Comment thread src/cprover/state_encoding.cpp Outdated
Comment thread src/cprover/state_encoding.cpp Outdated
@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.30435% with 31 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.78%. Comparing base (90da45f) to head (1cab0d4).

Files with missing lines Patch % Lines
src/cprover/simplify_state_expr.cpp 60.71% 22 Missing ⚠️
src/cprover/state_encoding.cpp 73.91% 6 Missing ⚠️
src/cprover/state_encoding_targets.cpp 75.00% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #9069      +/-   ##
===========================================
+ Coverage    80.68%   80.78%   +0.09%     
===========================================
  Files         1714     1714              
  Lines       189522   189606      +84     
  Branches        73       73              
===========================================
+ Hits        152925   153175     +250     
+ Misses       36597    36431     -166     

☔ View full report in Codecov by Harness.
📢 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.

@tautschnig tautschnig force-pushed the strata/cprover-state-encoding branch from 78c4acf to 6dcb7fe Compare June 19, 2026 08:16
tautschnig and others added 2 commits June 23, 2026 12:02
…lvalues

Three complementary state-encoding fixes:

- Leave mathematical-function (uninterpreted function) symbols unencoded as
  state variables, so the callee symbol of a function_application survives
  evaluate_expr_rec.
- Route member/index reads whose base is not an addressable lvalue (e.g. a
  function_application returning a struct) through the operand-recursion path,
  while addressable bases (symbol, dereference, string_constant) keep using
  the address-based path. The base of the access chain is found via a small
  member_index_base() helper using the typed accessors.
- Do not field-split an assignment whose RHS is a computed whole-struct value
  (a function_application or if-then-else, possibly behind typecasts),
  classified by is_whole_struct_value(), since splitting would re-evaluate the
  value once per field.

In the SMT2 target, struct (tuple) values returned by functions require
use_datatypes, which is therefore enabled (the targeted solvers support
declare-datatypes). The enter-scope-state element size falls back to a unit
size for mathematical pointee types (which have no byte size and are not
byte-addressed); any other type without a size is unexpected and now fails
loudly rather than silently using an arbitrary size.

Regression tests cover the if-then-else whole-struct assignment, the
mathematical-type enter-scope size fallback, and the datatype emission. The
uninterpreted-function and computed-struct member/index read behaviours are
exercised by the Strata front end (they require applied mathematical-function
symbols, which the in-tree cprover tool does not synthesise from C).

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Reading a field (or element) of an object that was updated with a whole
struct/array value was unsound in the state simplifier: evaluate of a
field-address against an update of the containing object was treated as
non-aliasing, so the whole-object update was dropped and the field read the
stale prior state. This produced spurious counterexamples, e.g. for

  struct S t; t = c ? a : b; assert(t.x == (c ? a.x : b.x));

Add three simplification rules to simplify_state_expr:
- evaluate(field_address(A, f), ς[A := V]) --> member(V, f), and likewise
  for element_address (the missing whole-object/sub-component overlap case);
- member(evaluate(ς, A), f) --> evaluate(ς, field_address(A, f)), and the
  analogous index rule, bridging the datatype (whole-value) view of a struct
  and the field-address (scalar) view so both agree;
- distribution of member/index over if, so the bridge applies to each arm of
  a conditional whole-struct value.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig tautschnig force-pushed the strata/cprover-state-encoding branch from 6dcb7fe to 1cab0d4 Compare June 23, 2026 12:03
@tautschnig tautschnig assigned kroening and unassigned tautschnig Jun 23, 2026
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.

3 participants