yaxunl created this revision. yaxunl added reviewers: tra, rjmccall. The Microsoft ABI requires that clang performs the destructor body checks (i.e. operator delete() lookup) when the vtable is marked used, as the deleting destructor is emitted with the vtable, not with the destructor definition as in the Itanium ABI. This can cause a CXXDestrcuctorDecl to be passed to CheckDestructor even though the CXXDestrcuctorDecl is not defined yet. Later on, if the same dtor is defined, it will be passed to CXXDestrcuctorDecl again. This causes assertion in Sema::markKnownEmitted.
This patch fixes that by let Sema::getEmissionStatus report correct emission state for the dtor passed to each CheckDestructor. https://reviews.llvm.org/D70172 Files: clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/SemaCUDA/deleting-dtor.cu
Index: clang/test/SemaCUDA/deleting-dtor.cu =================================================================== --- /dev/null +++ clang/test/SemaCUDA/deleting-dtor.cu @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsyntax-only -verify=MS -verify=GEN %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -fsyntax-only -verify=GEN %s + +#include "Inputs/cuda.h" +typedef long long __m256i __attribute__((__vector_size__(32))); + +namespace NoDiag { + struct CFileStream { + CFileStream(); + virtual ~CFileStream(); + }; + + struct CMultiFileStream { + CFileStream m_fileStream; + ~CMultiFileStream(); + }; + + CFileStream::CFileStream() {} + CFileStream::~CFileStream() {} + CMultiFileStream::~CMultiFileStream() {} +} + +// No diagnostic since deleting dtor is not emitted. +namespace NoVtbl { +// Intentionally generates delayed diagnostic about r0. +// This diagnostic is not supposed to be emitted unless f is emitted. + static __device__ __host__ void f(__m256i *p) { + __asm__ volatile("vmovaps %0, %%ymm0" ::"m"(*(__m256i *)p) + : "r0"); + } + struct CFileStream { + void operator delete(void *p) { + f(0); + } + CFileStream(); + virtual ~CFileStream(); + }; + + struct CMultiFileStream { + CFileStream m_fileStream; + ~CMultiFileStream(); + }; +} + +// Only MS has diagnostic since MS requires deleting dtor is emitted when +// vtable is emitted, even though dtor is not defined. +namespace MSEmitDeletingDtor { + static __device__ __host__ void f(__m256i *p) { + __asm__ volatile("vmovaps %0, %%ymm0" ::"m"(*(__m256i *)p) + : "r0"); // MS-error{{unknown register name 'r0' in asm}} + } + struct CFileStream { + void operator delete(void *p) { + f(0); // MS-note{{called by 'operator delete'}} + } + CFileStream(); + virtual ~CFileStream(); // MS-note{{called by '~CFileStream'}} + }; + + struct CMultiFileStream { + CFileStream m_fileStream; + ~CMultiFileStream(); + }; + + // This causes vtable emitted so that deleting dtor is emitted for MS. + CFileStream::CFileStream() {} +} + +namespace EmitDtor { + static __device__ __host__ void f(__m256i *p) { + __asm__ volatile("vmovaps %0, %%ymm0" ::"m"(*(__m256i *)p) + : "r0"); // GEN-error{{unknown register name 'r0' in asm}} + } + struct CFileStream { + void operator delete(void *p) { + f(0); + } + CFileStream(); + virtual ~CFileStream(); + }; + + struct CMultiFileStream { + CFileStream m_fileStream; + ~CMultiFileStream(); + }; + + CFileStream::~CFileStream() { + f(0); // GEN-note{{called by '~CFileStream'}} + } +} + Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -15629,8 +15629,13 @@ // If this is an out-of-line declaration, marking it referenced will // not do anything. Manually call CheckDestructor to look up operator // delete(). - ContextRAII SavedContext(*this, DD); - CheckDestructor(DD); + auto Loc = MSDeletingDtorsChecked.find(DD); + if (Loc == MSDeletingDtorsChecked.end()) { + MSDeletingDtorsChecked[DD] = false; + ContextRAII SavedContext(*this, DD); + CheckDestructor(DD); + MSDeletingDtorsChecked[DD] = true; + } } else { MarkFunctionReferenced(Loc, Class->getDestructor()); } Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -17684,6 +17684,20 @@ if (FD->isDependentContext()) return FunctionEmissionStatus::TemplateDiscarded; + // The Microsoft ABI requires that we perform the destructor body + // checks (i.e. operator delete() lookup) when the vtable is marked used, as + // the deleting destructor is emitted with the vtable. Such check may happen + // even though the destructor is not defined yet. We use + // MSDeletingDtorsChecked to indicate such checking and return Emitted. + // Once the check is done, we resume normal checking for the destructors. + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + if (auto *DD = dyn_cast<CXXDestructorDecl>(FD)) { + auto Loc = MSDeletingDtorsChecked.find(DD); + if (Loc != MSDeletingDtorsChecked.end() && !Loc->second) + return FunctionEmissionStatus::Emitted; + } + } + FunctionEmissionStatus OMPES = FunctionEmissionStatus::Unknown; if (LangOpts.OpenMPIsDevice) { Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -693,6 +693,14 @@ SmallVector<std::pair<FunctionDecl*, FunctionDecl*>, 2> DelayedEquivalentExceptionSpecChecks; + // The Microsoft ABI requires that we perform the destructor body + // checks (i.e. operator delete() lookup) when the vtable is marked used, as + // the deleting destructor is emitted with the vtable, not with the + // destructor definition as in the Itanium ABI. This map holds declared + // desructors (may or may not be defined later) and whether they have been + // checked. + llvm::DenseMap<CXXDestructorDecl *, bool> MSDeletingDtorsChecked; + typedef llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>> LateParsedTemplateMapT;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits