You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sema::SubstDecl crashes in InitMethodInstantiation on constructor templates of instantiated class templates (clang 22, --buggy-substitute-default-template-args) #34
Sema::SubstDecl call at src/parser/main.cpp:2815 (inside the --buggy-substitute-default-template-args code path) crashes inside clang::TemplateDeclInstantiator::InitMethodInstantiation with STATUS_ACCESS_VIOLATION (0xC0000005) on clang 22.1.4, when the visitor processes a constructor template member of an already-instantiated class template specialization.
This is the next-layer crash after #33 (which guarded InstantiateDefaultArgument and InstantiateFunctionDefinition on primary templates). With #33 merged the boost::multiprecision parse still segfaults on some builds; this issue tracks that remaining crash.
Trigger
Real-world: a Windows MSVC-target build that includes <boost/multiprecision/cpp_int.hpp> and passes --buggy-substitute-default-template-args. mrbind invocation (full args in the CI log linked below):
(meshlib.combined.hpp is a generated header that #includes all MeshLib public headers, which transitively pull in <boost/multiprecision/cpp_int.hpp>.)
The crash is flaky on some CI runs and reliable on others — the symptom is the same access violation in the same code path, but timing/cache state seems to influence whether it actually fires.
Stack trace
mrbind is built RelWithDebInfo; libclang-cpp.dll is stripped (msys2 default), so the libclang frames only have function names. Captured via the LLVM signal handler installed in main() (PR #33 second commit).
The crashing decl is a CXXConstructorDecl that's a member of a ClassTemplateSpecializationDecl reached via TraverseTemplateInstantiations. mrbind passes the constructor's templated decl to Sema::SubstDecl(templated_decl, templated_decl->getParent(), ml_targs). Clang's InitMethodInstantiation deref-faults on something the API doesn't validate.
Where mrbind calls into the bug
// src/parser/main.cpp:2691..2826 (inside VisitFunctionDecl)if (params->buggy_substitute_default_template_args && decl->isTemplated()
&& !ShouldRejectFunction(...)) {
if (auto templ = decl->getDescribedTemplate()) {
auto func_templ = llvm::dyn_cast<clang::FunctionTemplateDecl>(templ);
...
// Compute ml_targs from default template arguments.
...
clang::Sema::SFINAETrap trap(ci->getSema());
if (!trap.hasErrorOccurred()) {
...
auto ret = cast_or_null<clang::FunctionDecl>(
ci->getSema().SubstDecl(templated_decl, // ← line 2815
templated_decl->getParent(),
ml_targs));
...
}
}
}
When decl is a constructor template's templated decl whose enclosing class is a ClassTemplateSpecializationDecl, the SubstDecl call routes through VisitCXXMethodDecl → InitMethodInstantiation and segfaults.
Input: vcpkg 2024.10.21x64-windows-vs2019-meshlib's boost (1.86), transitively included via meshlib.combined.hpp.
I attempted several synthetic reproducers (Wrap<T> class templates with constructor templates in various shapes, including some that mirror boost::multiprecision::number's signature) on the same mrbind+toolchain locally and could not get them to fire this exact code path. The smallest reliable repro I have remains the full meshlib.combined.hpp parse from the linked CI run. Suggestions for what makes boost's ctor templates special here are very welcome — likely candidates: SFINAE in default args, enable_if chains, ctors that take other specializations of the same class template, or interaction with forward-declared template params.
Suggested directions for a fix
This is the same family as #33: mrbind drives a clang Sema entry point with inputs that don't match the API's implicit preconditions, and clang null-derefs instead of erroring cleanly. Two ways forward, not mutually exclusive:
mrbind-side guard. Skip the SubstDecl call when the templated decl is a CXXConstructorDecl (or any CXXMethodDecl) whose lexical parent is a ClassTemplateSpecializationDecl. Constructors of an instantiated class template don't need their primary template re-substituted by mrbind — clang already produced the per-spec ctor instantiations. If we can identify the trigger more precisely than "any ctor template inside any spec," the guard can be narrower. (This is the same shape of fix as in Parser: skip primary function templates in Sema instantiation calls #33.)
Upstream LLVM hardening.InitMethodInstantiation should be defensive against the inputs SubstDecl reaches it with on this path — at minimum assert with a clear message instead of null-deref. I plan to file a companion upstream issue against llvm/llvm-project if/when we have a reduced repro that crashes plain clang -fsyntax-only (haven't gotten there yet).
Workarounds
Remove --buggy-substitute-default-template-args from mrbind_flags.txt. Untested for behavioral side-effects on the generated bindings, but it bypasses this exact path.
Summary
Sema::SubstDeclcall atsrc/parser/main.cpp:2815(inside the--buggy-substitute-default-template-argscode path) crashes insideclang::TemplateDeclInstantiator::InitMethodInstantiationwithSTATUS_ACCESS_VIOLATION (0xC0000005)on clang 22.1.4, when the visitor processes a constructor template member of an already-instantiated class template specialization.This is the next-layer crash after #33 (which guarded
InstantiateDefaultArgumentandInstantiateFunctionDefinitionon primary templates). With #33 merged the boost::multiprecision parse still segfaults on some builds; this issue tracks that remaining crash.Trigger
Real-world: a Windows MSVC-target build that includes
<boost/multiprecision/cpp_int.hpp>and passes--buggy-substitute-default-template-args. mrbind invocation (full args in the CI log linked below):(meshlib.combined.hpp is a generated header that
#includes all MeshLib public headers, which transitively pull in<boost/multiprecision/cpp_int.hpp>.)The crash is flaky on some CI runs and reliable on others — the symptom is the same access violation in the same code path, but timing/cache state seems to influence whether it actually fires.
Stack trace
mrbindis builtRelWithDebInfo;libclang-cpp.dllis stripped (msys2 default), so the libclang frames only have function names. Captured via the LLVM signal handler installed inmain()(PR #33 second commit).The crashing decl is a
CXXConstructorDeclthat's a member of aClassTemplateSpecializationDeclreached viaTraverseTemplateInstantiations. mrbind passes the constructor's templated decl toSema::SubstDecl(templated_decl, templated_decl->getParent(), ml_targs). Clang'sInitMethodInstantiationderef-faults on something the API doesn't validate.Where mrbind calls into the bug
When
declis a constructor template's templated decl whose enclosing class is aClassTemplateSpecializationDecl, the SubstDecl call routes throughVisitCXXMethodDecl→InitMethodInstantiationand segfaults.Reproduction sources
windows-build-test (msvc-2019, Release, CMake, 2024.10.21, x64-windows-vs2019-meshlib)).Parser: install LLVM stack-trace signal handler in main).ci/use-runner-msys2(clang 22 toolchain probe — seeMeshInspector/MeshLib#6021).--target=x86_64-pc-windows-msvc.2024.10.21x64-windows-vs2019-meshlib's boost (1.86), transitively included via meshlib.combined.hpp.I attempted several synthetic reproducers (
Wrap<T>class templates with constructor templates in various shapes, including some that mirror boost::multiprecision::number's signature) on the same mrbind+toolchain locally and could not get them to fire this exact code path. The smallest reliable repro I have remains the full meshlib.combined.hpp parse from the linked CI run. Suggestions for what makes boost's ctor templates special here are very welcome — likely candidates: SFINAE in default args,enable_ifchains, ctors that take other specializations of the same class template, or interaction with forward-declared template params.Suggested directions for a fix
This is the same family as #33: mrbind drives a clang Sema entry point with inputs that don't match the API's implicit preconditions, and clang null-derefs instead of erroring cleanly. Two ways forward, not mutually exclusive:
mrbind-side guard. Skip the
SubstDeclcall when the templated decl is aCXXConstructorDecl(or anyCXXMethodDecl) whose lexical parent is aClassTemplateSpecializationDecl. Constructors of an instantiated class template don't need their primary template re-substituted by mrbind — clang already produced the per-spec ctor instantiations. If we can identify the trigger more precisely than "any ctor template inside any spec," the guard can be narrower. (This is the same shape of fix as in Parser: skip primary function templates in Sema instantiation calls #33.)Upstream LLVM hardening.
InitMethodInstantiationshould be defensive against the inputsSubstDeclreaches it with on this path — at minimum assert with a clear message instead of null-deref. I plan to file a companion upstream issue againstllvm/llvm-projectif/when we have a reduced repro that crashes plainclang -fsyntax-only(haven't gotten there yet).Workarounds
--buggy-substitute-default-template-argsfrommrbind_flags.txt. Untested for behavioral side-effects on the generated bindings, but it bypasses this exact path.--skip-mentions-of/--ignore(best effort; ours already filters some boost types but not multiprecision).