diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 8708bf99d91e7..83bafeb9aac61 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -166,7 +166,8 @@ class ByteCodeExprGen : public ConstStmtVisitor, bool>, if (!visitInitializer(Init)) return false; - if (Init->getType()->isRecordType() && !this->emitCheckGlobalCtor(Init)) + if ((Init->getType()->isArrayType() || Init->getType()->isRecordType()) && + !this->emitCheckGlobalCtor(Init)) return false; return this->emitPopPtr(Init); diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 8d7f191ebaa09..f646e876554ca 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -456,8 +456,11 @@ static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC, bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This) { assert(!This.isZero()); - const Record *R = This.getRecord(); - return CheckFieldsInitialized(S, OpPC, This, R); + if (const Record *R = This.getRecord()) + return CheckFieldsInitialized(S, OpPC, This, R); + const auto *CAT = + cast(This.getType()->getAsArrayTypeUnsafe()); + return CheckArrayInitialized(S, OpPC, This, CAT); } bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status) { diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp index 5d9fa90b482ea..87c32e42d053e 100644 --- a/clang/test/AST/Interp/cxx20.cpp +++ b/clang/test/AST/Interp/cxx20.cpp @@ -138,14 +138,43 @@ static_assert(!b4); // ref-error {{not an integral constant expression}} \ namespace UninitializedFields { class A { public: - int a; // expected-note 3{{subobject declared here}} \ - // ref-note 3{{subobject declared here}} + int a; // expected-note 4{{subobject declared here}} \ + // ref-note 4{{subobject declared here}} constexpr A() {} }; constexpr A a; // expected-error {{must be initialized by a constant expression}} \ // expected-note {{subobject 'a' is not initialized}} \ // ref-error {{must be initialized by a constant expression}} \ // ref-note {{subobject 'a' is not initialized}} + constexpr A aarr[2]; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{subobject 'a' is not initialized}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{subobject 'a' is not initialized}} + class F { + public: + int f; // expected-note 3{{subobject declared here}} \ + // ref-note 3{{subobject declared here}} + + constexpr F() {} + constexpr F(bool b) { + if (b) + f = 42; + } + }; + + constexpr F foo[2] = {true}; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{subobject 'f' is not initialized}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{subobject 'f' is not initialized}} + constexpr F foo2[3] = {true, false, true}; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{subobject 'f' is not initialized}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{subobject 'f' is not initialized}} + constexpr F foo3[3] = {true, true, F()}; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{subobject 'f' is not initialized}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{subobject 'f' is not initialized}} + class Base {