Files
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

83 lines
2.8 KiB
C++

// RUN: %clang_cc1 -triple x86_64-windows-msvc %s -emit-llvm -fexceptions -o - | FileCheck %s
// PR41065: As background, when constructing a complete object, virtual bases
// are constructed first. If an exception is thrown while constructing a
// subobject later, those virtual bases are destroyed, so sema references the
// relevant constructors and destructors of every base class in case they are
// needed.
//
// However, an abstract class can never be used to construct a complete object.
// In the Itanium C++ ABI, this works out nicely, because we never end up
// emitting the "complete" constructor variant, only the "base" constructor
// variant, which can be called by constructors of derived classes. For various
// reasons, Sema does not mark ctors and dtors of virtual bases referenced when
// the constructor of an abstract class is emitted.
//
// In the Microsoft ABI, there are no complete/base variants, so before PR41065
// was fixed, the constructor of an abstract class could reference special
// members of a virtual base without marking them referenced. This could lead to
// unresolved symbol errors at link time.
//
// The fix is to implement the same optimization as Sema: If the class is
// abstract, don't bother initializing its virtual bases. The "is this class the
// most derived class" check in the constructor will never pass, and the virtual
// base constructor calls are always dead. Skip them.
struct A {
A();
virtual void f() = 0;
virtual ~A();
};
// B has an implicit inline dtor, but is still abstract.
struct B : A {
B(int n);
int n;
};
// Still abstract
struct C : virtual B {
C(int n);
//void f() override;
};
// Not abstract, D::D calls C::C and B::B.
struct D : C {
D(int n);
void f() override;
};
void may_throw();
C::C(int n) : B(n) { may_throw(); }
// No branches, no constructor calls before may_throw();
//
// CHECK-LABEL: define dso_local noundef ptr @"??0C@@QEAA@H@Z"(ptr {{[^,]*}} returned align 8 dereferenceable(8) %this, i32 noundef %n, i32 noundef %is_most_derived)
// CHECK-NOT: br i1
// CHECK-NOT: {{call.*@"\?0}}
// CHECK: call void @"?may_throw@@YAXXZ"()
// no cleanups
D::D(int n) : C(n), B(n) { may_throw(); }
// Conditionally construct (and destroy) vbase B, unconditionally C.
//
// CHECK-LABEL: define dso_local noundef ptr @"??0D@@QEAA@H@Z"(ptr {{[^,]*}} returned align 8 dereferenceable(8) %this, i32 noundef %n, i32 noundef %is_most_derived)
// CHECK: icmp ne i32 {{.*}}, 0
// CHECK: br i1
// CHECK: call noundef ptr @"??0B@@QEAA@H@Z"
// CHECK: br label
// CHECK: invoke noundef ptr @"??0C@@QEAA@H@Z"
// CHECK: invoke void @"?may_throw@@YAXXZ"()
// CHECK: cleanuppad
// CHECK: call void @"??1C@@UEAA@XZ"
// CHECK: cleanupret
//
// CHECK: cleanuppad
// CHECK: icmp ne i32 {{.*}}, 0
// CHECK: br i1
// CHECK: call void @"??1B@@UEAA@XZ"
// CHECK: br label
// CHECK: cleanupret