https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/196544
>From bc2dedb178950e86afee2ef2af29d1029ca9cdf9 Mon Sep 17 00:00:00 2001 From: Iris Shi <[email protected]> Date: Fri, 8 May 2026 22:18:54 +0800 Subject: [PATCH 1/2] [clang][AST] Teach `CXXTypeidExpr::isMostDerived` to use `isEffectivelyFinal` --- clang/lib/AST/ExprCXX.cpp | 5 ++ clang/test/CodeGenCXX/typeid-most-derived.cpp | 57 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 clang/test/CodeGenCXX/typeid-most-derived.cpp 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..a2d9f2e2bc6eb --- /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 Poly { + virtual int foo() { return 42; } + virtual ~Poly(); +}; + +struct Derived : Poly {}; +struct Final final : Poly { + int foo() override { return 84; } +}; + +// Most derived +void value(Poly p) { typeid(p); } +// CHECK-LABEL: define {{.*}}void @_Z5value4Poly +// 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 poly_ref(Poly &p) { typeid(p); } +// CHECK-LABEL: define {{.*}}void @_Z8poly_refR4Poly +// CHECK: %vtable +// CHECK: ret void + +// Not most derived +void poly_deref(Poly *p) { typeid(*p); } +// CHECK-LABEL: define {{.*}}void @_Z10poly_derefP4Poly +// CHECK: %vtable +// CHECK: ret void + +// Not most derived +void derived_ref(Derived &d) { typeid(d); } +// CHECK-LABEL: define {{.*}}void @_Z11derived_refR7Derived +// CHECK: %vtable +// CHECK: ret void + +// Not most derived +void derived_deref(Derived *d) { typeid(*d); } +// CHECK-LABEL: define {{.*}}void @_Z13derived_derefP7Derived +// CHECK: %vtable +// CHECK: ret void >From a9257f7f1a7f1422db5160546f643d943c80b637 Mon Sep 17 00:00:00 2001 From: Iris Shi <[email protected]> Date: Mon, 11 May 2026 21:12:38 +0800 Subject: [PATCH 2/2] address review comments --- clang/docs/ReleaseNotes.rst | 3 ++ clang/test/CodeGenCXX/typeid-most-derived.cpp | 28 +++++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 40b97b4c8bf4b..0c6ad0707d196 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/test/CodeGenCXX/typeid-most-derived.cpp b/clang/test/CodeGenCXX/typeid-most-derived.cpp index a2d9f2e2bc6eb..2b6bb850ff415 100644 --- a/clang/test/CodeGenCXX/typeid-most-derived.cpp +++ b/clang/test/CodeGenCXX/typeid-most-derived.cpp @@ -4,19 +4,19 @@ namespace std { class type_info {}; } -struct Poly { +struct Base { virtual int foo() { return 42; } - virtual ~Poly(); + virtual ~Base(); }; -struct Derived : Poly {}; -struct Final final : Poly { +struct NonFinal : Base {}; +struct Final final : Base { int foo() override { return 84; } }; // Most derived -void value(Poly p) { typeid(p); } -// CHECK-LABEL: define {{.*}}void @_Z5value4Poly +void base_by_value(Base b) { typeid(b); } +// CHECK-LABEL: define {{.*}}void @_Z13base_by_value4Base // CHECK-NOT: %vtable // CHECK: ret void @@ -33,25 +33,25 @@ void final_deref(Final *f) { typeid(*f); } // CHECK: ret void // Not most derived -void poly_ref(Poly &p) { typeid(p); } -// CHECK-LABEL: define {{.*}}void @_Z8poly_refR4Poly +void base_ref(Base &b) { typeid(b); } +// CHECK-LABEL: define {{.*}}void @_Z8base_refR4Base // CHECK: %vtable // CHECK: ret void // Not most derived -void poly_deref(Poly *p) { typeid(*p); } -// CHECK-LABEL: define {{.*}}void @_Z10poly_derefP4Poly +void base_deref(Base *b) { typeid(*b); } +// CHECK-LABEL: define {{.*}}void @_Z10base_derefP4Base // CHECK: %vtable // CHECK: ret void // Not most derived -void derived_ref(Derived &d) { typeid(d); } -// CHECK-LABEL: define {{.*}}void @_Z11derived_refR7Derived +void nonfinal_ref(NonFinal &d) { typeid(d); } +// CHECK-LABEL: define {{.*}}void @_Z12nonfinal_refR8NonFinal // CHECK: %vtable // CHECK: ret void // Not most derived -void derived_deref(Derived *d) { typeid(*d); } -// CHECK-LABEL: define {{.*}}void @_Z13derived_derefP7Derived +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
