Author: Timm Baeder Date: 2025-10-28T08:35:48+01:00 New Revision: f49cd170c0a05875542d4e042265b05312fa00ef
URL: https://github.com/llvm/llvm-project/commit/f49cd170c0a05875542d4e042265b05312fa00ef DIFF: https://github.com/llvm/llvm-project/commit/f49cd170c0a05875542d4e042265b05312fa00ef.diff LOG: [clang][bytecode] Check overrider for pure virtual (#165262) Instead of checking the initial callee, check the callee after the virtual dispatch. This means we need to check whether we're in a ctor to not regress existing tests. Fixes https://github.com/llvm/llvm-project/issues/165234 Added: Modified: clang/lib/AST/ByteCode/Interp.cpp clang/test/AST/ByteCode/cxx20.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index d640be032b4f6..a2fb0fb331f8a 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1651,8 +1651,8 @@ static bool GetDynamicDecl(InterpState &S, CodePtr OpPC, Pointer TypePtr, QualType DynamicType = TypePtr.getType(); if (TypePtr.isStatic() || TypePtr.isConst()) { - const VarDecl *VD = TypePtr.getDeclDesc()->asVarDecl(); - if (!VD->isConstexpr()) { + if (const VarDecl *VD = TypePtr.getDeclDesc()->asVarDecl(); + VD && !VD->isConstexpr()) { const Expr *E = S.Current->getExpr(OpPC); APValue V = TypePtr.toAPValue(S.getASTContext()); QualType TT = S.getASTContext().getLValueReferenceType(DynamicType); @@ -1683,20 +1683,6 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset); const FunctionDecl *Callee = Func->getDecl(); - if (!Func->isFullyCompiled()) - compileFunction(S, Func); - - // 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; if (!GetDynamicDecl(S, OpPC, ThisPtr, DynamicDecl)) return false; @@ -1706,7 +1692,8 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, const auto *InitialFunction = cast<CXXMethodDecl>(Callee); const CXXMethodDecl *Overrider; - if (StaticDecl != DynamicDecl) { + if (StaticDecl != DynamicDecl && + !llvm::is_contained(S.InitializingBlocks, ThisPtr.block())) { if (!DynamicDecl->isDerivedFrom(StaticDecl)) return false; Overrider = S.getContext().getOverridingFunction(DynamicDecl, StaticDecl, @@ -1716,6 +1703,17 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, Overrider = InitialFunction; } + // C++2a [class.abstract]p6: + // the effect of making a virtual call to a pure virtual function [...] is + // undefined + if (Overrider->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; + } + if (Overrider != InitialFunction) { // DR1872: An instantiated virtual constexpr function can't be called in a // constant expression (prior to C++20). We can still constant-fold such a diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp index 1888998ebe3dd..cb788fa3e2c07 100644 --- a/clang/test/AST/ByteCode/cxx20.cpp +++ b/clang/test/AST/ByteCode/cxx20.cpp @@ -1183,3 +1183,21 @@ namespace VirtualFunctionCallThroughArrayElem { static_assert(a[2][3].foo()); // both-error {{not an integral constant expression}} \ // both-note {{virtual function called on object 'a[2][3]' whose dynamic type is not constant}} } + +namespace NonPureVirtualCall { + struct A { + constexpr virtual void call(int) = 0; + constexpr void call2() { call(0); } + }; + + struct B : A { + constexpr void call(int) override {} + }; + + consteval void check() { + B b; + b.call2(); + } + + int main() { check(); } +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
