Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -720,6 +720,28 @@ if (!this->emitPopPtr(Initializer)) return false; } + return true; + } else if (const auto *IVIE = dyn_cast(Initializer)) { + auto ArrayType = IVIE->getType()->getAsArrayTypeUnsafe(); + assert(ArrayType); + const auto *CAT = dyn_cast(ArrayType); + const size_t NumElems = CAT->getSize().getZExtValue(); + Optional ElemT = classify(CAT->getElementType()); + + if (ElemT) { + // TODO(perf): For int and bool types, we can probably just skip this + // since we memset our Block*s to 0 and so we have the desired value + // without this. + for (size_t I = 0; I != NumElems; ++I) { + if (!this->emitZero(*ElemT, Initializer)) + return false; + if (!this->emitInitElem(*ElemT, I, Initializer)) + return false; + } + } else { + assert(false && "default initializer for non-primitive type"); + } + return true; } Index: clang/test/AST/Interp/arrays.cpp =================================================================== --- clang/test/AST/Interp/arrays.cpp +++ clang/test/AST/Interp/arrays.cpp @@ -98,3 +98,15 @@ struct fred y [] = { [0] = { .s[0] = 'q' } }; #endif #pragma clang diagnostic pop + +namespace DefaultInit { + template + struct B { + T a[N]; + }; + + int f() { + constexpr B arr = {}; + constexpr int x = arr.a[0]; + } +};