Feed arithmetic length lower/upper/exact bounds (via theory_seq
lower_bound/upper_bound) into the monadic regex end-game solver using the
existing add_lo/add_hi/add_len helpers, so proposed witnesses respect length
constraints and length-driven cases resolve directly instead of backtracking
over the model.
Dependencies handed to the monadic solver now encode a union of sorts:
2*lit.index() for membership literals (even) and 2*bound_index+1 for length
bounds (odd). On unsat, the core is decoded back into conflict literals,
materializing the justifying arithmetic bound literals (len>=lo, len<=hi) at
that point. Bounds are recorded in m_monadic_bounds and undone via push_trail.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
The clang-tidy warning report surfaced a small set of high-confidence
analyzer findings with straightforward fixes: intentional null
dereference in debug-only crash paths, undefined oversized shifts in
`mpff`, uninitialized state in sorting-network setup, and `% 0` in a
unit test edge case.
- **Debug crash path**
- Replaced intentional null writes in `src/util/debug.cpp` with an
explicit crash helper based on `SIGSEGV`/`abort`.
- Keeps the failure mode intentional without relying on undefined
pointer dereference.
```c++
[[noreturn]] static void force_segfault() {
std::raise(SIGSEGV);
std::abort();
}
```
- **`mpff` integer extraction**
- Hardened `get_uint64` / `get_int64` against analyzer-reported
oversized right shifts.
- Computes the shift count in `int64_t`, asserts the valid range, and
guards the shift site.
- **Sorting-network initialization**
- Initialized `psort_nw::m_t` in the constructor to avoid
uninitialized-object diagnostics on construction paths that inspect
state before later assignment.
- **Test-only edge cases**
- Added an early return in `src/test/total_order.cpp` for `sz == 0` to
avoid `% 0` in randomized loops.
- Removed the extra trailing semicolon pattern around the `find_q`
namespace in `src/test/var_subst.cpp`.
- **Scope**
- Focused only on localized, semantics-preserving fixes from the warning
artifact.
- Left broader architectural warnings (for example,
constructor/destructor virtual-call diagnostics) out of this change.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
The clang-tidy warning fixer depended on
`download_workflow_run_artifact` to fetch the warning report from the
producer workflow. That path is blocked here, so the fixer could
discover the run but not access the warning contents it needs to
analyze.
- **Fixer input path**
- Update
`/home/runner/work/z3/z3/.github/workflows/build-warning-fixer.md` to
consume the triggering run via `list_workflow_jobs` + `get_job_logs`
- Remove the artifact-download flow from the workflow instructions
- Parse warning and status data from the build job log, with a grep
fallback if the structured summary is missing
- **Producer log contract**
- Update
`/home/runner/work/z3/z3/.github/workflows/clang-tidy-warning-report.yml`
to emit a stable, marker-delimited summary block at the end of the build
job log
- Include both build status and the extracted warning subset in that
block
- Leave artifact upload in place as optional output rather than a
required dependency
- **Workflow behavior**
- Make the fixer operate entirely from Actions logs, avoiding cross-run
artifact retrieval as part of its primary path
- Preserve the existing warning extraction model while shifting the
producer/consumer contract to log output
Example of the emitted log shape:
```text
CLANG_TIDY_WARNING_REPORT_BEGIN
CLANG_TIDY_STATUS_BEGIN
configure_status=0
build_status=0
CLANG_TIDY_STATUS_END
CLANG_TIDY_WARNINGS_BEGIN
123: warning: ...
CLANG_TIDY_WARNINGS_END
CLANG_TIDY_WARNING_REPORT_END
```
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This updates the Clang-Tidy Warning Fixer to run after
`clang-tidy-warning-report.yml` completes, consume that run’s warning
artifacts, and produce assignment-ready fix proposals as GitHub issues.
It replaces the previous self-build/PR-creation flow with
artifact-driven analysis and diff-first issue output.
- **Trigger + execution model**
- Switched workflow trigger from scheduled standalone runs to
`workflow_run` on **Clang-Tidy Warning Report** completion (with manual
dispatch retained).
- Keeps fixer analysis scoped to diagnostics from the originating report
run.
- **Artifact-driven diagnostics input**
- Removed in-fixer prebuild/clang-tidy compilation step.
- Updated agent instructions to resolve source run ID, list/download the
warning artifact, extract logs, and analyze
`warnings.txt`/`combined.log` from that artifact.
- **Output contract: PR → Issue**
- Replaced safe output target from `create-pull-request` to
`create-issue`.
- Issue content now requires:
- warning summary,
- skipped-warning rationale,
- proposed fixes as full unified diffs,
- assignment-ready checklist entries.
- **Workflow/runtime alignment**
- Regenerated lockfile to match source workflow changes.
- Added Actions toolset/permissions needed for run/artifact retrieval in
the agent runtime.
```yaml
on:
workflow_run:
workflows: ["Clang-Tidy Warning Report"]
types: [completed]
branches: [master]
```
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
The `Build Z3 with clang-tidy warnings` job was failing before
compilation due to an invalid `cmake --build` invocation. The workflow
passed a Ninja-only flag directly to CMake, so the job exited with
`Unknown argument -k` instead of producing the intended warning report.
- **Root cause**
- The workflow invoked:
```bash
cmake --build build --target shell test-z3 -k 0
```
- `-k 0` is a native Ninja argument and must be forwarded through CMake
after `--`.
- **Change**
- Update the clang-tidy warning workflow to pass native build-tool
arguments correctly:
```bash
cmake --build build --target shell test-z3 -- -k 0
```
- **Effect**
- The job can now reach the actual Ninja build instead of failing in
CMake argument parsing.
- This restores the intended behavior of collecting clang-tidy/build
diagnostics in the workflow artifact.
- **Files**
- `.github/workflows/clang-tidy-warning-report.yml`
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This is another PR towards the goal of getting Z3 to compile cleanly
when included via FetchContents into clang-tidy, which uses a pretty
strict set of warnings. (1 more flag after this!)
This one adds the flag -Wgnu-anonymous-struct. Z3 uses this anonymous
struct idiom, usually when using a struct as one of the members of a
union, as in:
```
union {
justification * m_js;
unsigned m_lidx;
struct {
enode * m_lhs;
enode * m_rhs;
};
};
```
This is not, strictly speaking, legal C++ (at least according to
Google's AI summary -- and the existence of this flag in Clang implies
that it is a GNU extension). You need to give the struct a member name
in the outer union to prevent the warning.
I'm of two minds on this. On the one hand it's not hurting anything, and
all the major compilers seem to support the idiom. On the other hand,
well, why do we have standards if we're going to ignore them in favor of
de-facto standards?
I submit this PR to show the size of the changes necessary to eliminate
the use of the extension. Personally, I'd do it, but I would gladly
withdraw the PR in favor of one that just silences the warning, if that
was the reviewer's preference.
Adds a scheduled workflow to build Z3 with the clang-tidy warning
configuration being tracked in detlefs' PRs, including the latest
`-Wgnu-anonymous-struct` flag from #10345. The workflow persists all
emitted warnings as an artifact so warning regressions can be reviewed
from each run.
- **Workflow**
- Adds `.github/workflows/clang-tidy-warning-report.yml`
- Runs daily and on manual dispatch
- Uses Ubuntu + CMake/Ninja with `clang` and `clang-tidy`
- **Warning coverage**
- Reuses the repository's existing Clang warning setup
- Layers in the current pending detlefs warning flag:
- `-Wgnu-anonymous-struct`
- **Artifacts**
- Captures:
- `configure.log`
- `build.log`
- `combined.log`
- `warnings.txt`
- `status.txt`
- Uploads them as a per-run artifact for inspection
- **Failure behavior**
- Still uploads logs on failure
- Marks the workflow failed if configure or build fails, so broken
clang-tidy runs are visible in Actions
```yaml
CC=clang CXX=clang++ cmake -GNinja -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_CXX_CLANG_TIDY=clang-tidy \
-DCMAKE_CXX_FLAGS="-Wgnu-anonymous-struct"
```
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
## Summary
An F* proof build failed to discharge a proof obligation because z3
returned `unknown` instead of the expected `unsat`. This PR fixes an
attributed nonlinear-arithmetic performance/completeness **regression**
in z3 that caused the failure.
- Originating F* build run:
https://github.com/Z3Prover/z3/actions/runs/30685489878
- Failing query:
`inputs/fstar-build-failures/run-30685489878/pulse/failedQueries-Pulse.Lib.PriorityQueue-3.smt2`
(`Z3Prover/bench`)
- Query label: `failedQueries-Pulse.Lib.PriorityQueue-3`
- z3 ref under test: `1ba30df028`
- **Expected result:** `unsat` — **Observed on ref under test:**
`unknown` (`:reason-unknown "canceled"`, i.e. the embedded `(set-option
:rlimit 5000000)` budget was exhausted).
The query embeds its own options (`smt.arith.solver=6`,
`smt.mbqi=false`, `auto_config=false`, `rlimit=5000000`, ...); all runs
below honor those embedded options.
## Root cause and attribution
Bisecting `./z3` between a known-good baseline
(`a05be8a291`, which returns `unsat`) and
the ref under test identified the first bad commit as:
> **`90fe0aa0f32d4cf66f3503c249d1878a39c0cf3c` — "Imp fix (#10304)"**
That commit adds `monomial_bounds::propagate_fixed_rows()` and calls it
from `nla::core::propagate()`, gated by the new parameter
`smt.arith.nl.propagate_fixed_rows` (default **true**). The routine
scans **all** LP rows on **every** nonlinear-propagation call, and calls
`lra.find_feasible_solution()` whenever anything is propagated. On this
obligation that extra work consumes the `rlimit` budget before a proof
is found, so a query that was previously `unsat` becomes `unknown`
(`canceled`). This is a pure performance/completeness regression from a
newly-added, parameter-gated heuristic — not a soundness issue in the
query.
## Fix
Default `smt.arith.nl.propagate_fixed_rows` to **false**, restoring the
pre-#10304 behaviour. The heuristic and its code are left intact and
remain available as opt-in via `smt.arith.nl.propagate_fixed_rows=true`,
pending a more efficient implementation (e.g. not re-scanning every row
on every propagation call).
This is a one-line change in `src/params/smt_params_helper.pyg`; no
solver check is weakened and the failing behaviour is not masked — the
regressing heuristic is simply returned to being opt-in.
## Reproduction and validation
All builds via `python3 scripts/mk_make.py && make -C build -j8`
(CMake/Ninja unavailable in this environment; the Makefile build
produces an equivalent binary).
| z3 | `smt.arith.nl.propagate_fixed_rows` | Result |
|---|---|---|
| baseline `a05be8a` | (n/a, pre-feature) | `unsat` |
| ref under test `1ba30df` | true (default) | `unknown` (canceled) |
| ref under test `1ba30df` | false (override) | `unsat` |
| **patched `1ba30df` (this PR)** | false (new default) | **`unsat`** |
Before the fix the query reproduced the `unknown`/`canceled` failure;
after the fix the patched binary returns the expected `unsat` with the
query's embedded options unchanged.
## Notes / uncertainty
This change restores correctness-preserving behaviour by disabling an
optional heuristic by default rather than reworking its cost model. A
follow-up could re-enable the heuristic once its per-propagation cost is
bounded (e.g. only scanning rows touched since the last call). Created
as a **draft** for maintainer review.
> [!WARNING]
> <details>
> <summary>Firewall blocked 1 domain</summary>
>
> The following domain was blocked by the firewall during workflow
execution:
>
> - `pypi.org`
>> To allow these domains, add them to the `network.allowed` list in
your workflow frontmatter:
>
> ```yaml
> network:
> allowed:
> - defaults
> - "pypi.org"
> ```
>
> See [Network
Configuration](https://github.github.com/gh-aw/reference/network/) for
more information.
>
> </details>
> Generated by [Fix a Z3 failure on an F* proof
obligation](https://github.com/Z3Prover/bench/actions/runs/30692520945)
· 398.4 AIC · ⌖ 21.5 AIC · ⊞ 9.4K ·
[◷](https://github.com/search?q=repo%3AZ3Prover%2Fz3+%22gh-aw-workflow-id%3A+fstar-build-fixer%22&type=pullrequests)
<!-- gh-aw-agentic-workflow: Fix a Z3 failure on an F* proof obligation,
engine: copilot, version: 1.0.65, model: claude-opus-4.8, id:
30692520945, workflow_id: fstar-build-fixer, run:
https://github.com/Z3Prover/bench/actions/runs/30692520945 -->
<!-- gh-aw-workflow-id: fstar-build-fixer -->
<!-- gh-aw-workflow-call-id: Z3Prover/bench/fstar-build-fixer -->
Co-authored-by: z3prover-ci-bot[bot] <305651407+z3prover-ci-bot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
check() now records the dependencies of an unsat subset in m_core, exposed via
ptr_vector<u_dependency> const& core(). On l_false it calls minimize_core:
with the new m_min_core flag (set_min_core, default true) it deletion-minimizes
to a minimal unsat subset containing only constraints that participate in the
contradiction; with the flag off it returns all membership dependencies.
Add unit tests asserting the core omits irrelevant constraints (e.g. x in a*,
x in ~a*, y in b* has core {x-constraints} only), exercising both flag states.
The test harness runs with minimization disabled by default.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
Replace the batch solve_and(mems) with an incremental interface:
void add(expr* term, expr* regex, u_dependency* d);
lbool check();
add() stores each (term, regex, dependency) triple in
m_memberships (vector<tuple<expr_ref, expr_ref, u_dependency*>>); the
dependency is retained for future unsat-core tracking and may be nullptr.
check() decides the accumulated conjunction (the former solve_and body) and
consumes the memberships; an empty conjunction is sat. Update the unit tests
and benchmark to the add()/check() API.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
Remove the obj_map<expr,expr*>* model out-parameter from solve/solve_and/
decide_dnf. Add an m_gen_model flag (default true) with set_gen_model(bool),
store the extracted model in m_model (reset at the top of decide_dnf), and
expose get_model(). Switch live_states out to expr_ref_vector and the
product_nonempty state vectors to ptr_vector<expr>. Simplify the concat case
of parse_term with all_of. Disable model generation in the sat-only unit
tests and the benchmark.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
- decompose and live_states now return bool instead of a bool& ok out-param.
- Use is_uninterp_const(t) in parse_term.
- Use braced pair init and structured bindings over obj_map iteration.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
This is another PR towards the goal of getting Z3 to compile cleanly
when included via FetchContents into clang-tidy, which uses a pretty
strict set of warnings. (2 more flags after this!)
The first of these was -Wctad-maybe-unsupported. That has to do with
"class template argument deduction" -- the flag requires template
deduction guides to be explicitly provided if templated types are used
in situations that requires argument deduction. This fired for various
uses of templated types in the utils directory.
I decided that this should be a case of if it ain't broke, don't fix it,
and explicitly disabled the warning in the Z3 build (which will override
the setting if the flag is enabled in a larger build including Z3, like
clang).
-----
The second flag has to do with the C++ "rule of 3". Here is Google's AI
summary (inf_s_integer is a class in Z3 that triggered the warning):
_This warning means your inf_s_integer class defines a custom copy
assignment operator but lacks a user-defined copy constructor, which the
C++ standard deprecates to encourage the "Rule of Three". To fix this,
explicitly declare and = default the copy constructor in your class
definition._
_...example of how to fix..._
_This updates your code to modern C++ standards, cleanly silencing the
warning._
This seemed like a good standard to follow, and didn't require too many
changes, so I propose them.
Three `clang-analyzer-deadcode.DeadStores` warnings flagged by
clang-tidy: redundant bit-shifts in the log2 functions and an
unreachable assignment in `def::from_row()`.
## Changes
- **`src/util/util.cpp`** — `log2()` and `uint64_log2()`: Remove `v >>=
1` in the final `if (v & 0x2)` block. Only `r |= 1` matters; `v` is
never read after that point.
```cpp
// Before
if (v & 0x2) {
v >>= 1; // dead store
r |= 1;
}
// After
if (v & 0x2) {
r |= 1;
}
```
- **`src/math/simplex/model_based_opt.cpp`** — `def::from_row()`: Remove
`sign = true` assignment when `div < 0`. `sign` is only consumed earlier
in the function (`if (!sign)`) and is not read again after this point.
<!-- START COPILOT CODING AGENT SUFFIX -->
- Fixes#10333
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Memoize derivative_cofactors per regex in an owning cache so each regex's
cofactors are computed once per top-level solve. The cache is reset at the
start of solve()/solve_and() and freed in the destructor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
Per-variable extra constraints are now expressed as additional (var in R')
memberships passed to solve_and, so the var_extra parameter is dropped from
solve/solve_and and the internal decide_dnf. Tests updated to route extra
constraints through solve_and.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
Extract the guard_set class (element-value set over derivative cofactor
guards) from the anonymous namespace in seq_monadic.cpp into a
self-contained guard_set.h / guard_set.cpp pair.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
## Summary
Register the opt-in seq_monadic benchmark harness in test-z3.
The harness reads either Z3_SEQ_BENCH_FILE or all SMT2 files under
Z3_SEQ_BENCH_DIR, supports Brz and light-Ant modes through
Z3_SEQ_MONADIC_MODE, and reports per-file CSV timing and verdict
information.
The `agent` job in the Clang-Tidy Warning Fixer workflow was spending
most of its runtime waiting on a full clang-tidy build, then failing
before it could complete its safe-output path. This change narrows the
prompt so the agent can make a bounded decision from early diagnostics
instead of treating the full build as a prerequisite.
- **Prompt guardrail**
- Add a runtime-budget section to the compiled workflow prompt in
`build-warning-fixer.lock.yml`.
- Instruct the agent to stop after it has enough diagnostics for one
safe fix, or after 15 minutes.
- **Build scope reduction**
- Switch initial diagnostic collection to a `shell`-only build.
- Explicitly avoid waiting for a full `shell + test-z3` clang-tidy build
before deciding whether to act.
- **Fallback behavior**
- Direct the agent to emit `noop` when it cannot reach a safe, validated
fix within the time budget.
- Keep `test-z3` optional unless it is already available or cheap to
build within the remaining budget.
Example of the new prompt guidance:
```yaml
- Use `cmake --build build --target shell -- -k 0 2>&1 | tee /tmp/gh-aw/agent/clang-tidy-build.log` for initial diagnostic collection.
- Do not wait for the full `shell` build to finish before deciding what to do.
- Stop once you have enough diagnostics for one small, high-confidence fix, or after 15 minutes.
- If no safe fix is ready in that budget, call `noop`.
```
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
## Summary
Pin constant elements extracted while parsing sequence terms so they
remain alive throughout monadic decomposition.
Without these references, character ASTs could be reclaimed while still
stored as raw pointers in decomposition atoms, causing assertion
failures, fast-fail exits, and access violations during derivative
construction.
The fix eliminates 26 previously observed process failures in the regex
benchmark corpus. No stack-depth bailout is needed for these failures.
Emscripten worker threads spawned for long-running Z3 operations (e.g.
`solver.check()`) are never cleaned up, keeping the Node.js process
alive after Z3 is done.
The `killThreads` helper already existed internally in `jest.ts` but was
never part of the public package.
## Changes
- **`src/kill-threads.ts`** (new) — extracts `killThreads(em)` into a
standalone module; calls `em.PThread.terminateAllThreads()` then polls
until all workers are gone (5 s timeout)
- **`src/node.ts`** — re-exports `killThreads` so it is part of the
published `z3-solver` API
- **`src/jest.ts`** — simplified to re-export from `./kill-threads`
instead of duplicating ~45 lines
- **`src/kill-threads.test.ts`** (new) — unit tests for the exported
function
- **`PUBLISHED_README.md`** — documents the new API
## Usage
```typescript
import { init, killThreads } from 'z3-solver';
const api = await init();
// ... use Z3 ...
await killThreads(api.em);
```
<!-- START COPILOT CODING AGENT SUFFIX -->
- Fixes#7070
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Replace the TPTP and Z3_TPTP_DUMP_SMT2 environment variables in
tptp_frontend.cpp with a new 'tptp' configuration module (src/params/tptp.pyg)
exposing tptp.root and tptp.dump_smt2 parameters.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
Light-weight Antimirov cofactors for seq_monadic
================================================
Overview
--------
The seq_monadic solver explores symbolic regex derivatives when
computing live
states and product transitions. Its original transition representation
used
Brzozowski cofactors.
This change adds a light-weight Antimirov representation. It first
computes the
existing Brzozowski cofactors and then decomposes targets whose outer
shape is
s1 | ... | sn
or
(s1 | ... | sn) . tail
into separate transitions. Concatenations are maintained in
right-associative
form, so a distributable union occurs as the head of the concatenation.
Targets are reconstructed with mk_regex_concat to preserve
normalization.
After decomposition, transitions with the same target are merged by
disjoining
their guards. The existing path-aware cofactor traversal and range
predicates
are therefore retained.
Example
-------
For
r = .* a .{k}
the Brzozowski cofactors have the shape
[a, r | .{k}]
[^a, r]
The light-weight Antimirov transformation produces
[., r]
[a, .{k}]
This preserves the language while avoiding the deterministic subset
states
that grow exponentially on this family.
Modes
-----
seq_monadic exposes two transition modes:
light_antimirov default
brzozowski retained as an explicit option
The implementation is seq_rewriter::light_ant_derivative_cofactors.
Correctness
-----------
The seq_monadic unit tests run in both modes. They cover character and
generic
element sequences, multiple and repeated variables, variable
constraints,
bounded loops, conjunctions of memberships, and witness construction. A
focused test checks the cofactor transformation above. The complete
94-test
unit suite used during evaluation passed. The benchmark harness is not
registered as a normal unit test; after detaching it, all 93 registered
tests
pass.
Benchmark evaluation
--------------------
The final optimized comparison used all 1,545 SMT2 files under
C:\git\bench\inputs\regexes. Each file was run in a separate process
with a
15-second timeout. There were 1,513 cases where both modes completed
without a
process failure or timeout.
Brzozowski Light-Ant
paired solver time 94.98 s 63.26 s
median solver time 1.734 ms 0.710 ms
derivative calls 5.70 M 3.39 M
cofactors 13.33 M 6.99 M
live states 2.74 M 0.44 M
product states 652.8 K 642.8 K
Light-Ant reduced paired solver time by 33.4%, derivative calls by
40.5%,
cofactors by 47.5%, and live states by 84.0%. It was faster on 1,091
cases;
Brzozowski was faster on 421 cases.
Light-Ant changed 131 Brzozowski undef results to sat. There were no
reverse
verdict changes and no mismatches against known sat/unsat statuses. Both
modes
had two timeouts. Process failures decreased from 30 to 27.
By corpus, paired solver time improved by 39.1% on ClemensRegex and by
11.9% on
MargusRegex.
Alternatives considered
-----------------------
Direct use of full Antimirov derivatives was also evaluated. It
introduced
large performance outliers, particularly around intersections, and
produced
additional undef results and timeouts. Disabling intersection-over-union
distribution improved some of these cases but remained slower and less
robust
than the light-weight transformation. The direct full-Ant mode was
therefore
removed from this change.
Copilot-Session: a2ce3573-4e15-4a4a-afb5-21e3cb04e4a2
This is another PR towards the goal of getting Z3 to compile cleanly
when included via FetchContents into clang-tidy, which uses a pretty
strict set of warnings. (Only 4 more warnings after this one!)
This PR adds -Wignored-qualifiers. It detects only one violation: a
function whose by-value return type (unsigned) has a const qualifier.
Here is the error message:
```
/Users/daviddetlefs/z3/src/math/lp/dioph_eq.cpp:1518:9: warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
1518 | const unsigned sub_index(unsigned k) const {
| ^~~~~
```
Seems worth fixing.
This updates the existing agentic workflow from generic build-warning
cleanup to a clang-tidy-based loop: compile Z3 with Clang, inspect
clang-tidy/compiler diagnostics, and open a PR only for small,
semantics-preserving fixes.
- **Workflow scope**
- Renames and repurposes `build-warning-fixer` as a clang-tidy warning
fixer.
- Keeps the existing agentic PR flow, but narrows it to clang/clang-tidy
findings from the current run.
- **Build/analyze path**
- Switches the authored workflow prompt to use the repo’s CMake + Ninja
build with `clang`/`clang++`.
- Enables `CMAKE_CXX_CLANG_TIDY=clang-tidy` and exports compile commands
for tool-driven analysis.
- Captures configure/build logs in the agent artifact directory for
post-run diagnosis.
- **Agent behavior**
- Instructs the agent to classify clang-tidy warnings, compiler
warnings, and build errors from the build log.
- Biases toward localized fixes only: e.g. `override`,
`[[maybe_unused]]`, `nullptr`, dead locals.
- Explicitly prefers `noop` over speculative edits when diagnostics are
broad, risky, or design-affecting.
- **Generated workflow**
- Regenerates the compiled lockfile to reflect the new prompt and
current auth/permission model used by other agentic workflows in this
repo.
```yaml
CC=clang CXX=clang++ cmake -GNinja -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_CXX_CLANG_TIDY=clang-tidy \
2>&1 | tee /tmp/gh-aw/agent/clang-tidy-configure.log
```
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
## Summary
Adds a global configuration parameter **`suppress_platform_verbose`**
(bool, default `false`).
When set to `true`, memory and time information is suppressed from
verbose output — the same behavior as the `-V` flag proposed in #10301,
but driven by a global parameter instead of a dedicated command-line
switch. This yields deterministic, platform-independent verbose output
that is useful for testing and diffing.
Usage:
```
z3 -v:2 suppress_platform_verbose=true problem.smt2
```
## Approach
Instead of introducing a `-V` command-line flag (#10301), this registers
`suppress_platform_verbose` as a global parameter via `env_params`,
wired to a lightweight `get_suppress_platform_verbose()` flag in `util`.
Verbose output sites guard only their **memory** (`mem_stat`) and
**time** (`m_watch` / `:time` / `:before-memory` / `:after-memory`)
fields on this flag. Platform-independent counters (e.g. `:cost`,
`:threshold`, `:elim-vars`) are always emitted.
Affected sites:
- SAT: asymm-branch, probing, scc, simplifier (subsumer /
blocked-clauses / resolution), solver stats (`sat.stats`, `:memory`,
`mk_stat`)
- SMT: context stats (`smt.stats`)
- Tactic report (`:time`, `:before-memory`, `:after-memory`)
## Validation
- Release build succeeds.
- `suppress_platform_verbose` appears in `z3 -pd` with the correct
type/default, and is accepted on the command line.
- All 93 `test-z3 /a` unit tests pass.
Closes the need for the `-V` switch in #10301.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 57b9b87e-950a-49ea-bbb3-ed585646a5a9
### What it does
Fixes an inverted precondition assertion in `grobner::pop_scope`
(`src/math/grobner/grobner.cpp`).
```cpp
void grobner::pop_scope(unsigned num_scopes) {
SASSERT(num_scopes >= get_scope_level()); // was reversed
unsigned new_lvl = get_scope_level() - num_scopes; // requires num_scopes <= level
...
m_scopes.shrink(new_lvl);
}
```
`get_scope_level()` returns `m_scopes.size()` (grobner.h). The body
computes
`new_lvl = get_scope_level() - num_scopes` and calls
`m_scopes.shrink(new_lvl)`,
which is only well-defined when `num_scopes <= get_scope_level()`. The
assertion
stated the opposite (`>=`), so in debug builds it would fire on any
valid partial
pop (e.g. popping one of several scopes) while failing to catch the
unsigned
underflow it was meant to guard against. Changed to `<=`.
### Evidence
- `get_scope_level() const { return m_scopes.size(); }`
(`src/math/grobner/grobner.h`).
- Compiled the translation unit with MSVC and `Z3DEBUG` defined (so the
`SASSERT`
is active): builds cleanly.
### What we did not verify
This is a debug-only (`SASSERT`) correctness fix and has no effect on
release
builds. No behavioral test was added.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ad2c295d-7523-48cf-b786-b435b833e3af
https://github.com/Z3Prover/z3/pull/10284 changed the UNREACHABLE macro
in debug.h to use __builtin_unreachable() to indicate to the compiler
that the
code leading it should be considered unreachable.
In https://github.com/Z3Prover/z3/pull/10295 Copilot figured out that
this was wrong: the unreachable macro makes calls, which shouldn't be
elided, and whose arguments should be evaluated. It partially fixed the
problem by declaring invoke_exit_action to be `[[noreturn]]`. This
eliminated warnings in non-debug builds, but when Z3_DEBUG is enabled,
`UNREACHABLE` ends with an invocation of `INVOKE_DEBUGER()`. This can
call `invoke_debugger()`, which *can* actually return (so it can't be
given the `[[noreturn]]` attribute. So we still get warnings in debug
builds.
This PR fixes those, creating a Z3_unreachable_case macro, which is just
a combination of `UNREACHABLE()` and `Z3_fallthrough`. It uses that in
the places that give warnings.
It seemed better to me to still have these cases have a single macro,
rather than `UNREACHABLE` followed by an explicit `Z3_fallthrough`; this
seemed to me like it would confuse people -- "how can you fall through
if this code is unreachable?" But I'm open to alternative suggestions!