Skip to content

Put an array's brackets where C++ puts them, everywhere - #61

Merged
matt-edmondson merged 1 commit into
mainfrom
claude/bold-planck-mxarux
Sep 13, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
claude/bold-planck-mxarux

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Closes #51.

SpellDeclarator exists to move an array's brackets onto the declarator, and its remarks claimed sole ownership of that rule. C reached it from six places. C++ reached it from one — a field — while MapToCppType quietly appended the brackets in type position for everything else:

int[] steps          // parameter
int[] steps;         // local
int[] collect()      // return type

None of those is C++. All three are hard errors in a generated header, and IsArray was added precisely so a generated constant table could be emitted — so an element type reaching a signature is on the route, not beside it.

Three sites, not the two the issue names. A VariableDeclaration standing as a class member had it too.

MapToCppType no longer spells brackets at all. The positions it is still reached from are ones C++ does not let an array stand in — a return type, a base type, an enumeration's underlying type — so brackets there were a compile error wearing the shape of a feature. SpellDeclarator also now handles a declarator with no name, which an unnamed parameter is: T[] rather than T [].

The test that was actually missing

C, Rust and Go are each checked by compiling what they write. C++ was not — which is why this survived. Every spelling around it was pinned, and a spelling can be pinned and still be one a compiler refuses.

CppGeneratedSourceCompilesTests compiles a header through g++. It was checked against the bug before the fix went in: with the generator reverted, g++ rejects the header with expected ',' or '...' before 'steps'. The first version of the test passed against the broken generator because the build had failed on a formatting rule and the old binary ran — worth saying, because a compile test that never saw the failure proves nothing.

Writing it turned up something worth stating, and it is now written down in CLAUDE.md rather than discovered again:

IsArray carries no bound, so of the positions that declare a name, only a parameter and an initialised constant table can hold one. A data member and a local both need a bound C++ can see.

That is exactly the pair the table IsArray exists for, so the exemplar is those two.

Coverage

  • CppGeneratorTests — the three spellings, including that a return type carries no brackets.
  • CppGeneratedSourceCompilesTests — a parameter subscripted in the body, so the spelling is load-bearing rather than merely present.

847/847 tests pass, including the C, Rust, Go and now C++ toolchain tests.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QGCMUrT3jBgmANHNHcPmBf


Generated by Claude Code

`SpellDeclarator` exists to move an array's brackets onto the declarator,
and its remarks claimed sole ownership of that rule. C reached it from six
places. C++ reached it from one — a field — while `MapToCppType` quietly
appended the brackets in type position for everything else, so a parameter
came out as `int[] steps`, a local as `int[] steps;` and a return type as
`int[] collect()`. None of those is C++; all three are hard errors in a
generated header.

Three sites rather than the two the issue names: a `VariableDeclaration`
standing as a class member had it too.

`MapToCppType` no longer spells brackets at all. The positions it is still
reached from are ones C++ does not let an array stand in — a return type, a
base type, an enumeration's underlying type — so brackets there were a
compile error wearing the shape of a feature.

`SpellDeclarator` now handles a declarator with no name, which an unnamed
parameter is: `T[]` rather than `T []`.

## The test that was missing

C, Rust and Go are each checked by compiling what they write. C++ was not,
which is why this survived: every spelling around it was pinned, and a
spelling can be pinned and still be one a compiler refuses.

`CppGeneratedSourceCompilesTests` compiles a header through g++. It was
checked against the bug before the fix — the reverted generator makes g++
reject the header with `expected ',' or '...' before 'steps'`.

Writing it turned up something worth stating: `IsArray` carries no bound,
so of the positions that declare a name, only a parameter and an initialised
constant table can hold one. A data member and a local both need a bound C++
can see. That is what the table `IsArray` was added for, so the exemplar is
those two, and the limitation is now written down rather than discovered
again.

847/847 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGCMUrT3jBgmANHNHcPmBf
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 19b3548 into main Sep 13, 2026
12 checks passed
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.

C++ generator emits T[] name for array-typed parameters and locals, which is not valid C++

2 participants