[clang][bytecode] Reject calls to pure virtual functions (#128412)

This commit is contained in:
Timm Baeder
2025-02-23 11:44:37 +01:00
committed by GitHub
parent 0f8769086e
commit 8102fec00b
2 changed files with 23 additions and 1 deletions

View File

@@ -1382,6 +1382,18 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
size_t ArgSize = Func->getArgSize() + VarArgSize;
size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
const FunctionDecl *Callee = Func->getDecl();
// C++2a [class.abstract]p6:
// the effect of making a virtual call to a pure virtual function [...] is
// undefined
if (Callee->isPureVirtual()) {
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_pure_virtual_call,
1)
<< Callee;
S.Note(Callee->getLocation(), diag::note_declared_at);
return false;
}
const CXXRecordDecl *DynamicDecl = nullptr;
{
@@ -1398,7 +1410,7 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
assert(DynamicDecl);
const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl());
const auto *InitialFunction = cast<CXXMethodDecl>(Func->getDecl());
const auto *InitialFunction = cast<CXXMethodDecl>(Callee);
const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
DynamicDecl, StaticDecl, InitialFunction);

View File

@@ -177,3 +177,13 @@ consteval int f(int i) {
return 2 * i;
}
static_assert(test(42));
namespace PureVirtual {
struct Abstract {
constexpr virtual void f() = 0; // both-note {{declared here}}
constexpr Abstract() { do_it(); } // both-note {{in call to}}
constexpr void do_it() { f(); } // both-note {{pure virtual function 'PureVirtual::Abstract::f' called}}
};
struct PureVirtualCall : Abstract { void f(); }; // both-note {{in call to 'Abstract}}
constexpr PureVirtualCall pure_virtual_call; // both-error {{constant expression}} both-note {{in call to 'PureVirtualCall}}
}