Skip to content

Write a C++ constant of an allocating type as const, not constexpr [patch] - #143

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/cpp-constexpr-string-101
Sep 30, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/cpp-constexpr-string-101

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #101

What was wrong

CppGenerator wrote constexpr on every constant field, whatever its type. That happened in two places: SpellStorage for FieldDeclaration, and GenerateField for a constant VariableDeclaration class member.

string maps to std::string, so the output was static constexpr std::string / inline constexpr std::string. That compiles only while the value fits libstdc++'s small-string buffer. A longer value fails in g++ 13 with "not a constant expression because it refers to a result of 'operator new'", and under C++17 it is never valid.

Change

  • A new IsLiteralType check covers the standard-library types the generator emits that allocate: std::string, std::vector, std::map and std::any.
  • A constant of one of these types is now written as:
    • inline const at namespace scope
    • inline static const inside a type
  • These keep constexpr as before:
    • literal types
    • pointers and references
    • caller-defined types, such as the reflection-table exemplar's holo::reflect::FieldInfo

Tests

  • CppGeneratedSourceCompilesTests.ALongConstantStringCompilesWhereverAConstantMayStand compiles a constant longer than the small-string buffer with the real C++ compiler, with -std=c++20 -pedantic. It covers three positions: namespace scope, a static field in a struct, and a class-member VariableDeclaration.
  • CppGeneratorTests.ConstantField_OfANonLiteralType_IsConstRatherThanConstexpr pins the spellings, and checks that int keeps constexpr.
  • With the generator change reverted, both tests fail. g++ reports the exact error from the issue.
  • Full suite: 989 passed, 0 failed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HsaGezbczZSL9fXfQafs7x


Generated by Claude Code

…texpr

A constant string field came out as static/inline constexpr std::string,
which compiles only while the value fits libstdc++'s small-string buffer
and never under C++17. A constant whose type is std::string, std::vector,
std::map or std::any is now inline const (inline static const in a type);
literal types, pointers, references and caller-defined types keep
constexpr.

Fixes #101

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

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 370138f into main Sep 30, 2026
14 checks passed
@matt-edmondson
matt-edmondson deleted the fix/cpp-constexpr-string-101 branch September 30, 2026 08:43
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++ constant string fields are emitted as constexpr std::string, which fails to compile once the value is longer than 15 characters

2 participants