Skip to content

Commit 09cd5a8

Browse files
authored
[clang][bytecode] Refuse to contruct objects with virtual bases (#110142)
1 parent d435acb commit 09cd5a8

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,25 @@ bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T) {
10431043
return false;
10441044
}
10451045

1046+
static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
1047+
const Pointer &ThisPtr) {
1048+
assert(Func->isConstructor());
1049+
1050+
const Descriptor *D = ThisPtr.getFieldDesc();
1051+
1052+
// FIXME: I think this case is not 100% correct. E.g. a pointer into a
1053+
// subobject of a composite array.
1054+
if (!D->ElemRecord)
1055+
return true;
1056+
1057+
if (D->ElemRecord->getNumVirtualBases() == 0)
1058+
return true;
1059+
1060+
S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
1061+
<< Func->getParentDecl();
1062+
return false;
1063+
}
1064+
10461065
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
10471066
uint32_t VarArgSize) {
10481067
if (Func->hasThisPointer()) {
@@ -1117,6 +1136,9 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
11171136
if (!CheckInvoke(S, OpPC, ThisPtr))
11181137
return cleanup();
11191138
}
1139+
1140+
if (Func->isConstructor() && !checkConstructor(S, OpPC, Func, ThisPtr))
1141+
return false;
11201142
}
11211143

11221144
if (!CheckCallable(S, OpPC, Func))

clang/test/AST/ByteCode/cxx23.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,21 @@ namespace VirtualBases {
158158
/// Calls the constructor of D.
159159
D d;
160160
}
161+
162+
#if __cplusplus >= 202302L
163+
struct VBase {};
164+
struct HasVBase : virtual VBase {}; // all23-note 1{{virtual base class declared here}}
165+
struct Derived : HasVBase {
166+
constexpr Derived() {} // all23-error {{constexpr constructor not allowed in struct with virtual base class}}
167+
};
168+
template<typename T> struct DerivedFromVBase : T {
169+
constexpr DerivedFromVBase();
170+
};
171+
constexpr int f(DerivedFromVBase<HasVBase>) {}
172+
template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {}
173+
constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // all23-error {{constant expression}} \
174+
// all23-note {{cannot construct object of type 'DerivedFromVBase<VirtualBases::HasVBase>' with virtual base class in a constant expression}}
175+
#endif
161176
}
162177

163178
namespace LabelGoto {

0 commit comments

Comments
 (0)