Files
TheRock/compiler/amd-llvm/clang/test/CIR/CodeGen/devirtualize.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

105 lines
3.4 KiB
C++

// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -std=c++20 -O0 -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -std=c++20 -O0 -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -std=c++20 -O0 -emit-llvm %s -o %t.ll
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
struct Base {
virtual ~Base();
virtual int foo();
};
struct Final final : Base {
~Final();
int foo() override;
};
// Devirtualized destructor call: calling a virtual destructor on a type
// that the compiler can statically resolve (e.g. a final class).
void test_devirtualized_dtor(Final *f) {
f->~Final();
}
// CIR-LABEL: @_Z23test_devirtualized_dtorP5Final
// CIR: cir.call @_ZN5FinalD1Ev({{.*}}) nothrow
// LLVM-LABEL: @_Z23test_devirtualized_dtorP5Final
// LLVM: call void @_ZN5FinalD1Ev(
// OGCG-LABEL: @_Z23test_devirtualized_dtorP5Final
// OGCG: call void @_ZN5FinalD1Ev(
// Devirtualized method call: calling a virtual method on a final class.
int test_devirtualized_method(Final *f) {
return f->foo();
}
// CIR-LABEL: @_Z25test_devirtualized_methodP5Final
// CIR: cir.call @_ZN5Final3fooEv(
// LLVM-LABEL: @_Z25test_devirtualized_methodP5Final
// LLVM: call noundef i32 @_ZN5Final3fooEv(
// OGCG-LABEL: @_Z25test_devirtualized_methodP5Final
// OGCG: call noundef i32 @_ZN5Final3fooEv(
// Covariant return type: clone() returns Final* in the derived class but
// Base* in the base. Because the return types differ, we skip devirtualization
// and go through the vtable.
struct Covariant : Base {
virtual Covariant* clone();
};
struct FinalCovariant final : Covariant {
FinalCovariant* clone() override;
};
Base* test_covariant_return(FinalCovariant *f) {
return static_cast<Covariant*>(f)->clone();
}
// CIR-LABEL: @_Z21test_covariant_returnP14FinalCovariant
// CIR: cir.vtable.get_virtual_fn_addr
// CIR: cir.call %{{.*}}({{.*}})
// LLVM-LABEL: @_Z21test_covariant_returnP14FinalCovariant
// LLVM: call {{.*}} %{{.*}}(
// OGCG-LABEL: @_Z21test_covariant_returnP14FinalCovariant
// OGCG: call {{.*}} %{{.*}}(
// FinalNoOverride: final class that does not override foo().
// The compiler knows the dynamic type, so it devirtualizes to Base::foo().
struct FinalNoOverride final : Base {};
void test_final_no_override() {
FinalNoOverride local;
local.foo();
}
// CIR-LABEL: @_Z22test_final_no_overridev
// CIR: cir.call @_ZN4Base3fooEv(
// LLVM-LABEL: @_Z22test_final_no_overridev
// LLVM: call noundef i32 @_ZN4Base3fooEv(
// OGCG-LABEL: @_Z22test_final_no_overridev
// OGCG: call noundef i32 @_ZN4Base3fooEv(
// Cross-class: method is defined in B but called through a C* (separate base).
// getCXXRecord(base)=C != devirtualizedClass=B, so devirtualization is cancelled
// and a virtual call is emitted.
struct CrossA { virtual void f(); };
struct CrossB : CrossA { void f() override; };
struct CrossC : CrossA { };
struct CrossMulti final : CrossB, CrossC {};
void test_cross_class(CrossMulti *m) { static_cast<CrossC *>(m)->f(); }
// CIR-LABEL: @_Z16test_cross_classP10CrossMulti
// CIR: cir.vtable.get_virtual_fn_addr
// CIR: cir.call %{{.*}}({{.*}})
// LLVM-LABEL: @_Z16test_cross_classP10CrossMulti
// LLVM: call void %{{.*}}(
// OGCG-LABEL: @_Z16test_cross_classP10CrossMulti
// OGCG: call void %{{.*}}(