Skip to content

Do not put a concept in an exported template parameter list - #260

Merged
ryanmrichard merged 1 commit into
masterfrom
fix_concept_mangling
Sep 17, 2026
Merged

ryanmrichard merged 1 commit into
masterfrom
fix_concept_mangling

Conversation

@ryanmrichard

Copy link
Copy Markdown
Member

Fixes the 8 undefined references that fail SCF test_cmake_build (ubuntu-latest, clang-18).

Root cause

GCC 14 does not encode a template parameter’s type-constraint in the mangled name. Clang 18+ does. On an explicitly instantiated template the two produce different symbols:

GCC    _ZN13tensorwrapper8generate21generate_eigen_systemIdEE...
Clang  _ZN13tensorwrapper8generate21generate_eigen_systemITkN3wtf8concepts13FloatingPointEdEE...

The wheels are built by GCC, so a Clang consumer of the C++ SDK asks for a symbol the library never exports. The gcc-14 leg links fine — that asymmetry is the giveaway that this is a mangling divergence, not a missing instantiation.

The call sites are SCF’s own Catch2 template tests (eigen_normal.cpp, jacobi_normal.cpp), which instantiate over <float> and <double>.

Reduced repro (confirms the mechanism)

A constrained template + extern template + explicit instantiation, library built by g++-14:

consumer wants result
g++-14 _ZN2tw3genIdEE... LINK OK
clang++-18 _ZN2tw3genITkN3wtf8concepts13FloatingPointEdEE... LINK FAILED
clang++-18 -fclang-abi-compat=17 _ZN2tw3genIdEE... LINK OK

The -fclang-abi-compat=17 row confirms Clang 18 introduced the constrained mangling. That flag is not a usable fix here — these are public wheels, and third-party Clang consumers cannot be required to pass a compatibility flag.

The fix

Declare the five exported templates with typename T and enforce the requirement with a static_assert in each definition. Internal helpers that are never exported (add_noise_impl, the *_spacing helpers, sort_eigenvalues) keep their concept constraints.

Affected: add_noise (×2), generate_eigen_system, generate_eigenvalues, random_orthogonal_matrix. A scan of the other ten ecosystem repos found no other constrained-and-explicitly-instantiated templates.

Verification

Each patched TU compiled with both g++-14 and clang++-18; the emitted manglings are now identical in all four files.

Behaviour note

Misuse moves from a call-site constraint error to a static_assert in the definition. In practice these templates are explicitly instantiated for float/double only, so any other T was already a link error.

🤖 Generated with Claude Code

GCC 14 does not encode a template parameter type-constraint in the mangled
name; Clang 18+ does. On an explicitly instantiated template the two
compilers therefore produce different symbols:

  GCC   _ZN13tensorwrapper8generate21generate_eigen_systemIdEE...
  Clang _ZN13tensorwrapper8generate21generate_eigen_systemITkN3wtf8concepts13FloatingPointEdEE...

The wheels are built by GCC, so a Clang consumer of the C++ SDK asks for a
symbol the library never exports. SCF test_cmake_build (ubuntu-latest,
clang-18) failed with 8 undefined references to generate_eigen_system<float>
and <double> from its Catch2 template tests, while the gcc-14 leg linked
fine -- the giveaway that this is a mangling divergence and not a missing
instantiation.

Fix: declare the five exported templates with `typename T` and enforce the
requirement with a static_assert in each definition. Internal helpers that
are never exported (add_noise_impl, the *_spacing helpers, sort_eigenvalues)
keep their constraints.

Verified by compiling each patched TU with BOTH g++-14 and clang++-18: the
emitted manglings are now identical. Reduced repro confirmed the mechanism
(a GCC-built .so links against a GCC consumer and fails against a Clang one;
clang -fclang-abi-compat=17 also links, confirming Clang 18 introduced the
constrained mangling).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ryanmrichard
ryanmrichard merged commit 21a2ed4 into master Sep 17, 2026
15 checks passed
@ryanmrichard
ryanmrichard deleted the fix_concept_mangling branch September 17, 2026 19:56
@github-actions

Copy link
Copy Markdown
Contributor

🚀 [bumpr] Bumped!
New version:v0.0.114
Changes:v0.0.113...v0.0.114

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.

1 participant