gen-c: lower the element type of a local array - #3449
Merged
Conversation
Closes #3448 var x : [4]GF16; -> GF16 x[4]; error: use of undeclared identifier 'GF16' The same element is `uint16_t` in a parameter (`uint16_t a[static 4]`) and in a struct field (`uint16_t f[4];`). Only the local path passed the t27 text through, because it gated on `is_primitive` -- and the note retiring that very gate sits two hundred lines below, on `param_type_to_c`: W583: this used to be gated on `is_primitive`, which lists only the integer scalars -- so `f32`, `f64`, `str`, `string` and `gf16` took the pass-through arm and reached C unmapped even after `type_to_c` learned them. Same sentence, same file, other position. Two more defects live in the same eight lines. `var x : []u8;` emitted `uint8_t x[];`, which is not a definition; and `var x : []const u8;` emitted `const u8* x`, because the qualifier lives INSIDE the element text and this path did not strip it. The first slice repair was wrong, and the corpus said so: rewriting every `[]T` local to a pointer broke `T x[] = { ... }`, which is legal C and takes its size from the initialiser list. +5 errors, nothing better, in the one file carrying the shape. `size.is_empty() && node.children.is_empty()` is that measurement kept as code. MEASURED, and this is the part that matters beyond this commit. CLANG'S DEFAULT -ferror-limit=20 HAS BEEN CENSORING EVERY TOTAL I HAVE PUBLISHED THIS SESSION. 141 files reach the limit. The corpus emits 15133 errors, not the 3849 reported. The per-file splits were sound, because they were counted per file; the totals were floors. this change 15133 -> 15126 3 files better, 0 worse #3447, re-measured 15188 -> 15133 published as 3849 -> 3825 The direction and the per-file conclusions stand; the magnitudes were understated. It surfaced because a repair that removes real errors showed a ZERO delta -- three files sitting at exactly 20 before and after. tools/backend_parity_table.py gains the fourth position. Its first probe there measured the wrong thing: `var x : T;` with no initialiser is declared by C and Rust and emitted by NEITHER Zig nor Verilog, so the table was reading their dead-code removal. Initialising from a parameter of the same type fixed it, and the self-check now covers all four positions. Four mutants, four dead. 14 seals refreshed in the same commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gHashTag
enabled auto-merge (squash)
September 8, 2026 02:03
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
This was referenced Sep 8, 2026
gHashTag
added a commit
that referenced
this pull request
Sep 8, 2026
Closes #3450 Refs #3448 One instrument had been censoring its own totals -- clang's default `-ferror-limit=20`, which made every C error count published for this repository a floor. The obvious next question is whether the others do the same, and nobody had asked. Planting 50 known errors per language: clang (default) 20 TRUNCATES clang (-ferror-limit=0) 50 complete rustc 50 complete zig 50 complete iverilog 50 complete (TWO diagnostic lines per error) yosys 1 ABORTS on the first error yosys is not capped, it stops. An error COUNT from it is 0 or 1 and means nothing; only its pass/fail is a measurement. THE FIXTURES WERE THE HARD PART, and two of the five were wrong in ways that read as findings about the compiler rather than about me: * the Zig fixture named its functions `f16` and `f32`, which SHADOW ZIG PRIMITIVES, so it failed with 2 errors of a different kind before reaching the undefined names -- indistinguishable from a cap; * the Verilog fixture used implicitly declared identifiers, which yosys treats as a WARNING, so it reported zero -- indistinguishable from silence. `--self-check` therefore requires each fixture to produce the expected KIND of diagnostic before its count is believed. WHAT IS NOT AFFECTED, measured rather than hoped: * acceptance counts. Clang's exit code is 1 with and without the limit on a failing file, and 0 on a clean one, so a count of FILES that compile cannot be censored by a per-file cap. Every `cc accepts N` figure stands. * the repository's gates. The only tool invoking `cc` is check_duplicate_agreement.py, and it reads `returncode`. * the Rust totals, since rustc reports completely. What was wrong is exactly the C error totals in my own reports: 3849 was 15188, 3825 was 15133, and after #3449 it is 15126. The tool DEGRADES rather than lying. A runner without zig or yosys checks the compilers it has and NAMES what it skipped; only a run with nothing available exits 2. That matters because the CI runner carries neither, and a gate that cannot run must say so rather than fail forever. Four controls: a planted truncation reddens it, a one-compiler PATH passes while naming four skips, an empty PATH exits 2, and a fixture that stops producing its error fails the self-check. Wired into Spec Guards, under a second. Co-authored-by: lab <lab@example.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3448
The same element is lowered everywhere else:
uint16_t a[static 4]uint16_t f[4];GF16 x[4];W583, in a position its own repair never reached
The local path gated on
is_primitive. Two hundred lines below, onparam_type_to_c, sits the note retiring exactly that gate:Same sentence, same file, other position. Two more defects live in the same
eight lines:
var x : []u8;emitteduint8_t x[];(not a definition), andvar x : []const u8;emittedconst u8* x(the qualifier lives inside theelement text).
The first slice repair was wrong, and the corpus said so
Rewriting every
[]Tlocal to a pointer brokeT x[] = { … }, which islegal C and takes its size from the initialiser list: +5 errors, nothing
better, in the one file carrying the shape. The condition
size.is_empty() && node.children.is_empty()is that measurement kept as code,and a test holds it.
Every error total I published this session was a floor
This is the finding worth more than the fix.
Clang's default
-ferror-limit=20was censoring the aggregate. 141 filesreach the limit. The corpus emits 15133 errors, not the 3849 I have been
reporting.
The per-file splits were sound — they were counted per file — and the
directions and conclusions stand. The magnitudes were understated.
It surfaced only because a repair that removes real errors showed a zero
delta: three files sitting at exactly 20 before and after.
Three files improve here:
math/property_test_template46→43,nn/hslm79→76,numeric/gf16151→150. Zero files worse.The tool
tools/backend_parity_table.pygains the fourth position. Its first probethere measured the wrong thing:
var x : T;with no initialiser is declared byC and Rust and emitted by neither Zig nor Verilog, so the table was reading
their dead-code removal rather than their lowering. Initialising from a
parameter of the same type fixed it; the self-check now covers all four
positions.
Mutation
is_primitivegate restoredconststrip removedFull suite: 2615 passed, 0 failed. 14 seals refreshed in the same commit.