diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 2f4a05a85753c0..c43f64901909ce 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1043,6 +1043,25 @@ bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T) { return false; } +static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func, + const Pointer &ThisPtr) { + assert(Func->isConstructor()); + + const Descriptor *D = ThisPtr.getFieldDesc(); + + // FIXME: I think this case is not 100% correct. E.g. a pointer into a + // subobject of a composite array. + if (!D->ElemRecord) + return true; + + if (D->ElemRecord->getNumVirtualBases() == 0) + return true; + + S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base) + << Func->getParentDecl(); + return false; +} + bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize) { if (Func->hasThisPointer()) { @@ -1117,6 +1136,9 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func, if (!CheckInvoke(S, OpPC, ThisPtr)) return cleanup(); } + + if (Func->isConstructor() && !checkConstructor(S, OpPC, Func, ThisPtr)) + return false; } if (!CheckCallable(S, OpPC, Func)) diff --git a/clang/test/AST/ByteCode/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp index 3c50c8927304c0..1803fb8ab2e9a4 100644 --- a/clang/test/AST/ByteCode/cxx23.cpp +++ b/clang/test/AST/ByteCode/cxx23.cpp @@ -158,6 +158,21 @@ namespace VirtualBases { /// Calls the constructor of D. D d; } + +#if __cplusplus >= 202302L + struct VBase {}; + struct HasVBase : virtual VBase {}; // all23-note 1{{virtual base class declared here}} + struct Derived : HasVBase { + constexpr Derived() {} // all23-error {{constexpr constructor not allowed in struct with virtual base class}} + }; + template struct DerivedFromVBase : T { + constexpr DerivedFromVBase(); + }; + constexpr int f(DerivedFromVBase) {} + template constexpr DerivedFromVBase::DerivedFromVBase() : T() {} + constexpr int nVBase = (DerivedFromVBase(), 0); // all23-error {{constant expression}} \ + // all23-note {{cannot construct object of type 'DerivedFromVBase' with virtual base class in a constant expression}} +#endif } namespace LabelGoto {