Skip to content

Commit

Permalink
[clang][bytecode] Refuse to contruct objects with virtual bases (llvm…
Browse files Browse the repository at this point in the history
  • Loading branch information
tbaederr authored Sep 27, 2024
1 parent d435acb commit 09cd5a8
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
22 changes: 22 additions & 0 deletions clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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))
Expand Down
15 changes: 15 additions & 0 deletions clang/test/AST/ByteCode/cxx23.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 09cd5a8

Please sign in to comment.