gen-c: type a one-element literal list, from the field that holds it - #3462
Merged
Conversation
Refs #3459 334 of the remaining 837 `__auto_type x = { ... }` errors were one-element lists. The previous pass filed them rather than guessing: `[7]` arrives as an `ExprArrayLiteral` with ZERO children while the emitted C still reads `{ 7 }`, and `children` and `value` had both been searched and both were empty. The field is `extra_size`, and the comment naming it sits on the emitter arm FORTY LINES from the code that reads it: the parser stores the literal's ELEMENT TEXT in extra_size ("1,2,3" for a list, "0;4" for a repeat) with no children Two ends had to move together: the condition upstream still demanded non-empty `children`, and the declarator took its length from `children.len()`. Both now read `extra_size`, with the repeat form `v;n` taking `n` as the length rather than counting commas. MEASURED, whole corpus, -ferror-limit=0: errors 14276 -> 14165 __auto_type with initializer list 837 -> 670 files better 18 Two files rise and both are unmasking. Across two passes the class has gone 1729 -> 670. A MUTANT WAS BETTER THAN MY GUARD FOR ONE INPUT. Deleting the dotted-token check types `[1.2.3]` as `double x[1] = { 1.2.3 }` -- a malformed literal inside a well-formed declaration -- so the guard is load-bearing. But its first version required digits on BOTH sides of the dot, which refuses `1.`, and `1.` is valid C. The mutant exposed both halves at once: needed AND wrong. It now accepts at most one dot with digits on at least one side. `.5` is refused and stays refused: the lexer drops the leading dot and emits `{ 5 }`, so the value is corrupt before this code sees it, and typing a corrupted initialiser turns a loud error into a quiet wrong answer. The theoretical risk is named rather than hidden. A one-element list whose sole element is a QUOTED all-digit string, `["12"]`, is indistinguishable in `extra_size` from `[12]`, because the quotes are gone by then -- the old binary emitted `{ 12 }` too. Corpus population of that form: ZERO, measured, against 22 single-element string lists whose contents are not digits and which the inference refuses. Three mutants, three dead. 32 seals refreshed in the same commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gHashTag
enabled auto-merge (squash)
September 8, 2026 04:38
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
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.
Refs #3459
334 of the remaining 837
__auto_type x = { … }errors were one-elementlists. The previous pass filed them rather than guessing:
[7]arrives as anExprArrayLiteralwith zero children while the emitted C still reads{ 7 }, andchildrenandvaluehad both been searched and both were empty.The field is
extra_size— and the comment naming it sits on the emitterarm forty lines from the code that reads it:
Two ends had to move together: the condition upstream still demanded non-empty
children, and the declarator took its length fromchildren.len(). Both nowread
extra_size, with the repeat formv;ntakingnas the length ratherthan counting commas.
Measured —
-ferror-limit=0__auto_typewith initializer listTwo files rise and both are unmasking. Across two passes the class has gone
1729 → 670.
A mutant was better than my guard, for one input
Deleting the dotted-token check types
[1.2.3]asdouble x[1] = { 1.2.3 }—a malformed literal inside a well-formed declaration — so the guard is
load-bearing. But its first version required digits on both sides of the
dot, which refuses
1., and1.is valid C.The mutant exposed both halves at once: the check was needed and wrong.
It now accepts at most one dot with digits on at least one side.
[1.5]doubledouble[1.]double[1.2.3][a.b].5is refused and stays refused: the lexer drops the leading dot and emits{ 5 }, so the value is corrupt before this code sees it. Typing a corruptedinitialiser turns a loud error into a quiet wrong answer.
The theoretical risk, named
["12"]— a one-element list whose sole element is a quoted all-digit string —is indistinguishable in
extra_sizefrom[12], because the quotes are goneby then; the old binary emitted
{ 12 }too. Corpus population of that form:0, measured, against 22 single-element string lists whose contents are not
digits and which the inference refuses.
Full suite: 2642 passed, 0 failed. 32 seals refreshed in the same commit.