Skip to content

Commit 8102fec

Browse files
authored
[clang][bytecode] Reject calls to pure virtual functions (#128412)
1 parent 0f87690 commit 8102fec

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,18 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
13821382
size_t ArgSize = Func->getArgSize() + VarArgSize;
13831383
size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
13841384
Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1385+
const FunctionDecl *Callee = Func->getDecl();
1386+
1387+
// C++2a [class.abstract]p6:
1388+
// the effect of making a virtual call to a pure virtual function [...] is
1389+
// undefined
1390+
if (Callee->isPureVirtual()) {
1391+
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_pure_virtual_call,
1392+
1)
1393+
<< Callee;
1394+
S.Note(Callee->getLocation(), diag::note_declared_at);
1395+
return false;
1396+
}
13851397

13861398
const CXXRecordDecl *DynamicDecl = nullptr;
13871399
{
@@ -1398,7 +1410,7 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
13981410
assert(DynamicDecl);
13991411

14001412
const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl());
1401-
const auto *InitialFunction = cast<CXXMethodDecl>(Func->getDecl());
1413+
const auto *InitialFunction = cast<CXXMethodDecl>(Callee);
14021414
const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
14031415
DynamicDecl, StaticDecl, InitialFunction);
14041416

clang/test/AST/ByteCode/cxx2a.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,13 @@ consteval int f(int i) {
177177
return 2 * i;
178178
}
179179
static_assert(test(42));
180+
181+
namespace PureVirtual {
182+
struct Abstract {
183+
constexpr virtual void f() = 0; // both-note {{declared here}}
184+
constexpr Abstract() { do_it(); } // both-note {{in call to}}
185+
constexpr void do_it() { f(); } // both-note {{pure virtual function 'PureVirtual::Abstract::f' called}}
186+
};
187+
struct PureVirtualCall : Abstract { void f(); }; // both-note {{in call to 'Abstract}}
188+
constexpr PureVirtualCall pure_virtual_call; // both-error {{constant expression}} both-note {{in call to 'PureVirtualCall}}
189+
}

0 commit comments

Comments
 (0)