Skip to content

Fix generator escaping / name-collision compile-break class - #51

Merged
aaylward merged 1 commit into
mainfrom
claude/issue-27-fix-42z1s0
Jul 8, 2026
Merged

aaylward merged 1 commit into
mainfrom
claude/issue-27-fix-42z1s0

Conversation

@aaylward

@aaylward aaylward commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Closes #43 (top-tier from the whole-project review). Four generator paths emitted C++ that silently fails to compile for legal-but-unusual Smithy models, with no generation-time diagnostic.

Fixes

  • Enum value-set validation message interpolated raw wire values into a string literal (ValidationGenerator.writeEnumCheck); a value containing " or \ broke it. Now escaped in place via a new CppLiterals.escapeStringBodybyte-identical output for the common safe case, so no golden churn.
  • @pattern raw-string delimiter: the pattern was emitted verbatim inside R"__smithy(...)__smithy", so a value containing the closing sequence )__smithy" terminated the literal early. Rejected at generation time with a message naming the shape and the fix.
  • int64 minimum literals: @default and @range bounds emitted -9223372036854775808, which C++ can't parse (negation of a value one past int64_t max). Now emitted via the header-free INT64_MIN idiom (CppLiterals.int64Literal); only the minimum changes, every other magnitude stays byte-identical.
  • Enum/union name-folding collisions: enum-constant and union-factory naming lower-case / strip separators / PascalCase the member name, so two distinct members (or a member named unknown) could fold to one C++ name → duplicate enumerator/method. Now detected and failed at generation time with a diagnostic naming both members (or the reserved kUnknown).

Testing

  • New codegen unit tests, one per fix: enum-value escaping (asserts the escaped bytes appear and the raw form does not), raw-string-delimiter rejection (using a valid regex that contains the sequence — Smithy validates @pattern as a real regex), enum name-fold collision (foo_bar vs foo__bar, both fold to kFooBar — reachable because Smithy shape IDs are case-insensitive so case-only collisions can't occur), the kUnknown-sentinel collision, and the int64-min @range/@default idiom.
  • gradle build spotlessCheck green; regeneration produces zero golden diff (git diff --stat -- examples protocol-tests is empty — the guards only fire on previously-broken input).
  • bazel test //protocol-tests/... //examples/cafe/... (the enum/validation paths): 20/20 pass.

Checklist

  • Tests added/updated for the change (five codegen unit tests covering each fix)
  • bazel test //... and (cd codegen && gradle build spotlessCheck) pass locally (Beast/benchmark excluded per docs)
  • Formatting clean (spotless; no generated-code churn)
  • Architectural decisions recorded as an ADR (not applicable — bug fixes within existing conventions)

Note: a compile-the-generated-output test harness — which would catch this whole class structurally rather than case-by-case — is tracked separately in #48.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SyQAo21Pv6GYhHrkbQj8xQ


Generated by Claude Code

Several generator paths emitted C++ that silently fails to compile for
legal-but-unusual Smithy models, with no generation-time diagnostic
(issue #43):

- Enum value-set validation message interpolated raw wire values into a
  string literal; a value containing " or \ broke it. Escape the values
  in place (byte-identical output for the common safe case) via a new
  CppLiterals.escapeStringBody.
- @pattern was emitted verbatim inside R"__smithy(...)__smithy"; a
  pattern containing the closing delimiter )__smithy" terminated the raw
  literal early. Reject such patterns at generation time.
- @default and @range int64 minimum emitted -9223372036854775808, which
  C++ cannot parse (negation of a value one past int64 max). Emit the
  header-free INT64_MIN idiom via CppLiterals.int64Literal; only the
  minimum changes, everything else stays byte-identical.
- Enum-constant and union-factory name folding could map two distinct
  members (or a member named "unknown") to one C++ name, producing a
  duplicate enumerator/method. Detect the collision and fail generation
  with a diagnostic naming both members and the fix.

Tests: codegen unit tests for each — enum-value escaping, raw-string
delimiter rejection, enum name-fold collision, the kUnknown-sentinel
collision, and the int64-min range/default idiom. Regeneration produces
zero golden churn (guards only fire on previously-broken input).

Closes #43

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyQAo21Pv6GYhHrkbQj8xQ
@aaylward
aaylward merged commit 529824d into main Jul 8, 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.

Generator emits uncompilable C++ for legal-but-unusual models (escaping / name-collision class)

2 participants