Handle empty type in incremental SMT2 decision procedure#8907
Handle empty type in incremental SMT2 decision procedure#8907tautschnig wants to merge 2 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #8907 +/- ##
===========================================
- Coverage 80.57% 80.56% -0.01%
===========================================
Files 1708 1708
Lines 189217 189242 +25
Branches 73 73
===========================================
+ Hits 152460 152467 +7
- Misses 36757 36775 +18 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR fixes incremental SMT2 backend crashes caused by empty_typet (void) appearing in expressions that the solver attempts to convert to SMT sorts. It aligns the incremental backend’s behavior with the legacy/non-incremental SMT2 path for equality over empty types and re-enables previously excluded regression tests.
Changes:
- Skip empty-typed symbols/nondet symbols when gathering dependent expressions to avoid attempting SMT sort conversion.
- Add a defensive early return to avoid declaring SMT functions for empty-typed symbols.
- Treat equality over empty type as vacuously true in
set_to, mirroring the non-incremental SMT2 backend behavior; re-enable affected regression tests.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp |
Avoid SMT sort conversion / declarations for empty_typet and short-circuit == over empty type in set_to. |
regression/cbmc/memset_null/test.desc |
Remove no-new-smt exclusion tag now that incremental SMT2 passes the test. |
regression/cbmc/havoc_slice_checks/test.desc |
Remove no-new-smt exclusion tag now that incremental SMT2 passes the test. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cf62050 to
2dae3bc
Compare
2dae3bc to
8fc0c35
Compare
is_zero_width(const typet &, const namespacet &) was a file-static
helper in src/solvers/smt2/smt2_conv.cpp. The predicate is generic
('does this type have effective width of zero bits?') and not
specific to the non-incremental SMT2 backend; the incremental SMT2
backend will need exactly the same predicate to detect empty-typed
expressions correctly without re-treading the same struct/union/
struct-tag/union-tag/array recursion. Move the function to
src/util/pointer_offset_size.{h,cpp} alongside its semantic
neighbours pointer_offset_size and pointer_offset_bits, drop the
'static' qualifier on the original definition, and remove the
duplicate body from smt2_conv.cpp.
No functional change. smt2_conv.cpp continues to call is_zero_width
through the shared header (which it already includes); other
back-ends and util-level call sites can now do the same.
Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Skip zero-width-typed leaves (typically void) in
gather_dependent_expressions so that we never attempt to call
convert_type_to_smt_sort on them, which would hit
UNIMPLEMENTED_FEATURE. Handle the only top-level consumer that
could legitimately involve such a leaf -- equality of two
zero-width-typed operands -- by short-circuiting set_to: for
value == true the equality is vacuously satisfied (no command
emitted); for value == false we send `(assert false)` directly.
This matches the end-to-end behaviour of the non-incremental SMT2
backend, which converts equal_exprt over a zero-width type to
true_exprt and then negates.
Both filter sites use the shared is_zero_width predicate (now
exposed via util/pointer_offset_size.h) rather than a narrow
ID_empty check, so they stay correct even if struct_encoding's
pre-pass ever stops normalising other zero-width forms.
The set_to short-circuit handles only the top-level equality.
Nested cases such as and_exprt{equal_exprt{x_void, y_void}, other}
would still reach convert_expr_to_smt and trip
UNIMPLEMENTED_FEATURE; CBMC's GOTO programs do not produce such
nested shapes today, but pushing the short-circuit into the
equal_exprt overload of convert_expr_to_smt (mirroring
smt2_conv.cpp's structure more closely) is left as a follow-up.
Add a focused unit test in
unit/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp
covering both set_to(equal_exprt{void_x, void_y}, true) (no extra
commands sent) and set_to(..., false) (a single `(assert false)`).
Remove the no-new-smt exclusion tag from havoc_slice_checks and
memset_null regression tests since they now pass with the
incremental SMT2 backend.
Fixes: diffblue#8077
Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
8fc0c35 to
38c1921
Compare
Skip symbols and nondet symbols with empty_typet (void) in gather_dependent_expressions to avoid attempting SMT sort conversion. Add early return in send_function_definition for empty-typed expressions as a defensive measure. Handle equality over empty type in set_to by treating it as vacuously true, matching the behavior of the non-incremental SMT2 backend.
Remove no-new-smt exclusion tag from havoc_slice_checks and memset_null regression tests since they now pass with the incremental SMT2 backend.
Fixes: #8077