Skip to content

fix: escape trigraphs in C and C++ string literals [patch] - #164

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/107-c-trigraph-escapes
Oct 6, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/107-c-trigraph-escapes

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #107

What was wrong

C up to C17, and C++ before C++17, replace trigraphs inside string literals.

  • "what??!" compiled with gcc -std=c11 printed what|.
  • ??/ became a backslash that escaped the next character, which could swallow the closing quote.

Change

  • CFamilyGenerator now overrides EscapeString. After the shared escaping, it writes the second ? of every ?? pair as \?.
    • \? is a question mark in every C and C++ standard, so the string's value doesn't change.
    • Every trigraph is broken, including longer runs: ???! becomes ?\?\?!.
    • A lone ? (for example "ok?") is written as it was.
  • LanguageGeneratorBase.EscapeString is now protected virtual so the C family can override it.
  • C#, Go, Rust, Python and JavaScript keep the shared escaping. \? is not an escape in Go, Rust or JavaScript.
  • Assertion messages in C and C++ also go through EscapeString, so they are covered too.

Tests

New file: Coder.Test/Languages/StringLiteralTrigraphTests.cs.

  • CFamilyBreaksEveryTrigraph (C and C++): pins the exact literal written for every trigraph, a ???! run and a lone ?, and asserts that no ?? is left.
  • OtherLanguagesWriteQuestionMarksAsIs (C#, JavaScript, Python, Go and Rust): question marks are written unchanged.
  • CompiledWithTrigraphsOn_TheStringsKeepTheirValue:
    • Generates a header whose functions return "what??!" and "a??/b".
    • Compiles it with -std=c11 -Wall -Wextra -pedantic -Werror=trigraphs and runs it.
    • It uses the same ToolchainHarness as the existing compile tests, and is inconclusive when no C compiler is on the path.

With the CFamilyGenerator change reverted, three tests fail: both CFamilyBreaksEveryTrigraph rows and the compile-and-run test. The full suite passes: 1070 passed, 0 skipped.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NfxXtpcxX8hkLYrePfHkV4


Generated by Claude Code

C up to C17, and C++ before C++17, replace trigraphs such as ??! and ??/
inside string literals, so "what??!" compiled with -std=c11 printed what|
and ??/ became a backslash escaping the next character.

CFamilyGenerator now overrides EscapeString to write the second ? of every
?? pair as \?, which is a question mark in every C and C++ standard and
breaks every trigraph without touching a lone ?. EscapeString becomes
virtual for this; the other languages keep the shared escaping, since \? is
not an escape in Go, Rust or JavaScript.

Fixes #107

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

sonarqubecloud Bot commented Oct 6, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 53713d9 into main Oct 6, 2026
14 checks passed
@matt-edmondson
matt-edmondson deleted the fix/107-c-trigraph-escapes branch October 6, 2026 02:13
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: string literals containing ??!, ??/ etc. are rewritten by trigraphs under -std=c11 ("what??!" prints what|)

2 participants