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

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Sun Feb 23 02:13:10 PST 2025


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/128412

None

>From 5bb0213254e070c3c24492d6b7ec6810b13f5455 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sun, 23 Feb 2025 11:10:43 +0100
Subject: [PATCH] [clang][bytecode] Reject calls to pure virtual functions

---
 clang/lib/AST/ByteCode/Interp.cpp | 14 +++++++++++++-
 clang/test/AST/ByteCode/cxx2a.cpp | 10 ++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index dfa59a50b2711..61f67fbdba81f 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1377,6 +1377,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;
   {
@@ -1393,7 +1405,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);
 
diff --git a/clang/test/AST/ByteCode/cxx2a.cpp b/clang/test/AST/ByteCode/cxx2a.cpp
index 72ef58ca0b1d1..d9541aca225b9 100644
--- a/clang/test/AST/ByteCode/cxx2a.cpp
+++ b/clang/test/AST/ByteCode/cxx2a.cpp
@@ -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}}
+}



More information about the cfe-commits mailing list