Author: Joseph Huber Date: 2026-03-06T09:49:15-06:00 New Revision: 9e15c6cc3358287e93a25d869a31ab14c1791dcb
URL: https://github.com/llvm/llvm-project/commit/9e15c6cc3358287e93a25d869a31ab14c1791dcb DIFF: https://github.com/llvm/llvm-project/commit/9e15c6cc3358287e93a25d869a31ab14c1791dcb.diff LOG: [CUDA/HIP] Do not ignore complete destructors in abstract classes (#184894) Summary: The complete destructor destroys virtual base subobjects even for abstract classes, so target inference must consider vbases when analyzing destructors. This was motivated by behavior observed from a bug where a constexpr function that calls a non-constexpr function. I believe this error is secondary, but can be fixed by this observation. The issue was the switch to C++20 allowing allocator destructors to be constexpr began opting the function into `__host__ __device__` contexts. This function then called a non-constexpr function through a type-trait interface which lead to that only having `__host__` which is illegal. The fix offered here is to check the bases of this function and correctly derive that it is `__host__` and not `__host__ __device__` as was previously inferred. This should only affect cases where the *only* member is an inherited virtual destructor. Previously we found no bases and thus made no judgement. Fixes: https://github.com/llvm/llvm-project/issues/184856 Added: clang/test/SemaCUDA/dtor-constexpr-virtual-base.cu Modified: clang/lib/Sema/SemaCUDA.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index 6c40b92ddfa12..c086f9a32ce4e 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -496,7 +496,9 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, // Look for special members in base classes that should be invoked from here. // Infer the target of this member base on the ones it should call. - // Skip direct and indirect virtual bases for abstract classes. + // Skip direct and indirect virtual bases for abstract classes, except for + // destructors — the complete destructor variant destroys virtual bases + // regardless of whether the class is abstract. llvm::SmallVector<const CXXBaseSpecifier *, 16> Bases; for (const auto &B : ClassDecl->bases()) { if (!B.isVirtual()) { @@ -504,9 +506,8 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, } } - if (!ClassDecl->isAbstract()) { + if (!ClassDecl->isAbstract() || CSM == CXXSpecialMemberKind::Destructor) llvm::append_range(Bases, llvm::make_pointer_range(ClassDecl->vbases())); - } for (const auto *B : Bases) { auto *BaseClassDecl = B->getType()->getAsCXXRecordDecl(); diff --git a/clang/test/SemaCUDA/dtor-constexpr-virtual-base.cu b/clang/test/SemaCUDA/dtor-constexpr-virtual-base.cu new file mode 100644 index 0000000000000..1c4d88a62f21a --- /dev/null +++ b/clang/test/SemaCUDA/dtor-constexpr-virtual-base.cu @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify=host +// RUN: %clang_cc1 %s -std=c++20 -fcuda-is-device -fsyntax-only -verify=dev + +// host-no-diagnostics +// dev-no-diagnostics + +#include "Inputs/cuda.h" + +// The implicit destructor of an abstract class with virtual bases should +// consider those virtual bases during CUDA target inference, since the +// complete destructor variant destroys them. +void host_only(); + +constexpr void wraps_host() { + if (!__builtin_is_constant_evaluated()) + host_only(); +} + +struct HasDtor { + ~HasDtor() { wraps_host(); } +}; + +struct Base { + HasDtor m; + virtual ~Base(); +}; + +template <class T> +struct Derived : virtual public Base { + virtual void foo() = 0; +}; + +template class Derived<int>; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
