[Clang][Modules] Crash in ASTContext::getCanonicalTagType during lazy deserialization on namespace reopen
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
## Description
Clang crashes in `ASTContext::getCanonicalTagType()` during lazy deserialization of declarations from a precompiled module (PCM). The crash is triggered when a translation unit imports a module and then re-opens a namespace used within that module.
## Trigger pattern
```cpp
import strongai.type.tagged_union; // module with deep template instantiation chain
namespace StrongAI {
int x = 0; // re-opening the namespace triggers lazy deserialization -> crash
}
```
## Crash path
1. Parser encounters `namespace StrongAI {` -> `ActOnStartNamespaceDef`
2. Qualified lookup triggers `FindExternalVisibleDeclsByName`
3. `ASTReader` begins lazy deserialization: `FinishedDeserializing` -> `finishPendingActions` -> `loadDeclUpdateRecords` -> `UpdateDecl`
4. While reading a template argument list, `readTypeRecord` needs a canonical type
5. `ASTContext::getCanonicalTagType` follows a corrupted/stale `TagDecl*` and crashes (recursive call visible in trace)
## Stack trace
```
#5 clang::ASTContext::getCanonicalTagType(clang::TagDecl const*) const
#6 clang::ASTContext::getCanonicalTagType(clang::TagDecl const*) const
#7 clang::ASTReader::readTypeRecord(unsigned long long)
#8 clang::ASTReader::GetType(unsigned long long)
#9 clang::serialization::BasicReaderBase::readTemplateArgument()
#10 clang::ASTRecordReader::readTemplateArgumentList(...)
#11 clang::ASTDeclReader::UpdateDecl(clang::Decl*)
#12 clang::ASTReader::loadDeclUpdateRecords(...)
#13 clang::ASTReader::finishPendingActions()
#14 clang::ASTReader::FinishedDeserializing()
#15 clang::ASTReader::FindExternalVisibleDeclsByName(...)
#16 clang::DeclContext::lookupImpl(...)
#17 LookupDirect(...)
#18 clang::Sema::LookupQualifiedName(...)
#19 clang::Sema::ActOnStartNamespaceDef(...)
#20 clang::Parser::ParseNamespace(...)
```
## Reproducer status
A self-contained minimal reproducer has not been achieved. The crash requires a deep module graph (10+ PCM layers through a CRTP injection chain with template class specializations). Simpler module hierarchies do not trigger the crash.
The critical structure is: a module that re-exports multiple partitions, each containing deeply nested template class hierarchies with CRTP base chains, where the final module's namespace `StrongAI` contains many TagDecl entries that are lazily deserialized with DeclUpdateRecords containing template arguments referencing types from the deep chain.
Clang's crash reproducer (preprocessed source + run script) was generated but still requires the project's prebuilt PCMs to reproduce. If helpful for diagnosis, I can provide the complete project tree.
## Environment
- **Clang version**: 23.0.0git (commit 3392ec8cf17ce90fe0859ae31e86cf48f8fa185d)
- **OS**: macOS 15.4 (Darwin 25.3.0), ARM64
- **Target**: arm64-apple-macosx26.0.0
Contributor guide
Assessment
This issue has not been assessed yet.