Author: Iris Shi
Date: 2026-05-11T21:54:32+08:00
New Revision: 6443657de563bfb5870529e92075a2c13e9f4acb

URL: 
https://github.com/llvm/llvm-project/commit/6443657de563bfb5870529e92075a2c13e9f4acb
DIFF: 
https://github.com/llvm/llvm-project/commit/6443657de563bfb5870529e92075a2c13e9f4acb.diff

LOG: [clang][AST] Teach `CXXTypeidExpr::isMostDerived` to use 
`isEffectivelyFinal` (#196544)

Resolves #196476.

When a class is marked final, typeid on references to that type can be
resolved at compile time since the most-derived type is statically
known.

Added: 
    clang/test/CodeGenCXX/typeid-most-derived.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ExprCXX.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 53f3d42270f1a..bd91b8723a5c6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -250,6 +250,9 @@ Non-comprehensive list of changes in this release
   enabling tools such as language servers and refactoring engines to accurately
   map source locations back to explicit instantiation sites.
 
+- ``typeid`` on references and pointers of ``final`` types no longer emits a
+  vtable lookup at runtime.
+
 New Compiler Flags
 ------------------
 - New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added

diff  --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index be1bd3ba913ea..40e129d03dcea 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -149,6 +149,11 @@ bool CXXTypeidExpr::isPotentiallyEvaluated() const {
 bool CXXTypeidExpr::isMostDerived(const ASTContext &Context) const {
   assert(!isTypeOperand() && "Cannot call isMostDerived for typeid(type)");
   const Expr *E = getExprOperand()->IgnoreParenNoopCasts(Context);
+
+  if (const CXXRecordDecl *RD = E->getType()->getAsCXXRecordDecl())
+    if (RD->isEffectivelyFinal())
+      return true;
+
   if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
     QualType Ty = DRE->getDecl()->getType();
     if (!Ty->isPointerOrReferenceType())

diff  --git a/clang/test/CodeGenCXX/typeid-most-derived.cpp 
b/clang/test/CodeGenCXX/typeid-most-derived.cpp
new file mode 100644
index 0000000000000..2b6bb850ff415
--- /dev/null
+++ b/clang/test/CodeGenCXX/typeid-most-derived.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -Wno-unused-value -emit-llvm 
-o - -std=c++11 | FileCheck %s
+
+namespace std {
+  class type_info {};
+}
+
+struct Base {
+  virtual int foo() { return 42; }
+  virtual ~Base();
+};
+
+struct NonFinal : Base {};
+struct Final final : Base {
+    int foo() override { return 84; }
+};
+
+// Most derived
+void base_by_value(Base b) { typeid(b); }
+// CHECK-LABEL: define {{.*}}void @_Z13base_by_value4Base
+// CHECK-NOT:   %vtable
+// CHECK:       ret void
+
+// Most derived
+void final_ref(Final &f) { typeid(f); }
+// CHECK-LABEL: define {{.*}}void @_Z9final_refR5Final
+// CHECK-NOT:   %vtable
+// CHECK:       ret void
+
+// Most derived
+void final_deref(Final *f) { typeid(*f); }
+// CHECK-LABEL: define {{.*}}void @_Z11final_derefP5Final
+// CHECK-NOT:   %vtable
+// CHECK:       ret void
+
+// Not most derived
+void base_ref(Base &b) { typeid(b); }
+// CHECK-LABEL: define {{.*}}void @_Z8base_refR4Base
+// CHECK:       %vtable
+// CHECK:       ret void
+
+// Not most derived
+void base_deref(Base *b) { typeid(*b); }
+// CHECK-LABEL: define {{.*}}void @_Z10base_derefP4Base
+// CHECK:       %vtable
+// CHECK:       ret void
+
+// Not most derived
+void nonfinal_ref(NonFinal &d) { typeid(d); }
+// CHECK-LABEL: define {{.*}}void @_Z12nonfinal_refR8NonFinal
+// CHECK:       %vtable
+// CHECK:       ret void
+
+// Not most derived
+void nonfinal_deref(NonFinal *d) { typeid(*d); }
+// CHECK-LABEL: define {{.*}}void @_Z14nonfinal_derefP8NonFinal
+// CHECK:       %vtable
+// CHECK:       ret void


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to