diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -945,6 +945,37 @@ assert(false && "default initializer for non-primitive type"); } + return true; + } else if (const auto *Ctor = dyn_cast(Initializer)) { + const ConstantArrayType *CAT = + Ctx.getASTContext().getAsConstantArrayType(Ctor->getType()); + assert(CAT); + size_t NumElems = CAT->getSize().getZExtValue(); + const Function *Func = getFunction(Ctor->getConstructor()); + if (!Func || !Func->isConstexpr()) + return false; + + // FIXME(perf): We're calling the constructor once per array element here, + // in the old intepreter we had a special-case for trivial constructors. + for (size_t I = 0; I != NumElems; ++I) { + if (!this->emitDupPtr(Initializer)) + return false; + if (!this->emitConstUint64(I, Initializer)) + return false; + if (!this->emitAddOffsetUint64(Initializer)) + return false; + if (!this->emitNarrowPtr(Initializer)) + return false; + + // Constructor arguments. + for (const auto *Arg : Ctor->arguments()) { + if (!this->visit(Arg)) + return false; + } + + if (!this->emitCall(Func, Initializer)) + return false; + } return true; } diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -185,6 +185,40 @@ } }; +class A { +public: + int a; + constexpr A(int m = 2) : a(10 + m) {} +}; +class AU { +public: + int a; + constexpr AU() : a(5 / 0) {} // expected-warning {{division by zero is undefined}} \ + // expected-note {{division by zero}} \ + // ref-error {{never produces a constant expression}} \ + // ref-note 2{{division by zero}} \ + // ref-warning {{division by zero is undefined}} +}; +class B { +public: + A a[2]; + constexpr B() {} +}; +constexpr B b; +static_assert(b.a[0].a == 12, ""); +static_assert(b.a[1].a == 12, ""); + +class BU { +public: + AU a[2]; + constexpr BU() {} // expected-note {{in call to 'AU()'}} \ + // ref-note {{in call to 'AU()'}} +}; +constexpr BU bu; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{in call to 'BU()'}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{in call to 'BU()'}} + namespace IncDec { // FIXME: Pointer arithmethic needs to be supported in inc/dec // unary operators