https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/110142
None >From cfbd9ae7f7d8c671ae7248cf24138d058d9143e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Thu, 26 Sep 2024 18:19:09 +0200 Subject: [PATCH] [clang][bytecode] Refuse to contruct objects with virtual bases --- clang/lib/AST/ByteCode/Interp.cpp | 22 ++++++++++++++++++++++ clang/test/AST/ByteCode/cxx23.cpp | 15 +++++++++++++++ 2 files changed, 37 insertions(+) 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 9d7e9d753e6d2f..b51f761ce0caf6 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<typename T> struct DerivedFromVBase : T { + constexpr DerivedFromVBase(); + }; + constexpr int f(DerivedFromVBase<HasVBase>) {} + template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {} + constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // all23-error {{constant expression}} \ + // all23-note {{cannot construct object of type 'DerivedFromVBase<VirtualBases::HasVBase>' with virtual base class in a constant expression}} +#endif } namespace LabelGoto { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits