[Clang] ICE in AggExprEmitter::VisitCXXParenListOrInitListExpr when aggregate-initializing array-of-aggregates member in template class constructor
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Clang crashes (segfault) during codegen when a template class constructor uses parenthesized aggregate initialization (C++20, P0960) in its member initializer list to initialize a struct member containing an array of aggregates.
Reproducer
```cpp
struct Inner { int x; };
struct Outer { Inner arr[2]; };
template
struct S {
S() : m({{1}, {2}}) {}
Outer m;
};
template struct S;
```
```bash
$ clang++ -std=c++20 -c repro.cpp
```
https://godbolt.org/z/f7o3vn6vT
Crashes at all optimization levels (-O0 through -O3) and all C++20+ standard modes (-std=c++20, -std=c++23, -std=c++2c).
Conditions
All of the following must be true to trigger the crash:
1. The containing class is a template (non-template classes compile fine)
2. The member is a struct containing a C-array of aggregates (e.g. struct { Inner arr[N]; })
3. The initialization uses parenthesized aggregate init in a member initializer list
Also reproduces with `std::array, N>` (which wraps a C-array of pair aggregates):
```cpp
#include
#include
template
struct S {
S() : a({{1, 2}}) {}
std::array, 1> a;
};
template struct S;
```
Does not crash when
- The class is not a template
- The member is initialized via explicit constructor call (e.g. `m(Outer{Inner{1}, Inner{2}})`)
- The initialization is a default member initializer instead of a mem-initializer-list
- The inner aggregate type is replaced with a scalar
Stack trace
```
#0 llvm::sys::PrintStackTrace(...)
#1 llvm::sys::RunSignalHandlers()
#2 CrashRecoverySignalHandler(int)
#3 __restore_rt
#4 clang::TagDecl::getDefinition() const
#5 (anonymous namespace)::AggExprEmitter::VisitCXXParenListOrInitListExpr(...) CGExprAgg.cpp
#6 clang::CodeGen::CodeGenFunction::EmitAggExpr(...)
#7 (anonymous namespace)::AggExprEmitter::VisitCXXParenListOrInitListExpr(...) CGExprAgg.cpp
#8 clang::CodeGen::CodeGenFunction::EmitAggExpr(...)
#9 clang::CodeGen::CodeGenFunction::EmitInitializerForField(...)
#10 EmitMemberInitializer(...) CGClass.cpp
#11 clang::CodeGen::CodeGenFunction::EmitCtorPrologue(...)
#12 clang::CodeGen::CodeGenFunction::EmitConstructorBody(...)
#13 clang::CodeGen::CodeGenFunction::GenerateCode(...)
```
Version
clang version 22.1.2
Target: x86_64-unknown-linux-gnu
Contributor guide
Research direction
Start in CGExprAgg.cpp at AggExprEmitter::VisitCXXParenListOrInitListExpr and reproduce the crash with the supplied C++20 template example using clang++ -std=c++20 -c repro.cpp. Trace how the aggregate member initializer is handled during constructor code generation. Done means the reproducer and equivalent std::array case compile without a crash across the affected standard modes and optimization levels.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100