diff --git a/lib/IRGen/GenClangDecl.cpp b/lib/IRGen/GenClangDecl.cpp index 243beee7aa5fe..922d283a6e88e 100644 --- a/lib/IRGen/GenClangDecl.cpp +++ b/lib/IRGen/GenClangDecl.cpp @@ -228,18 +228,20 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) { // Unfortunately, implicitly defined CXXDestructorDecls don't have a real // body, so we need to traverse these manually. if (auto *dtor = dyn_cast(next)) { - auto cxxRecord = dtor->getParent(); + if (dtor->isImplicit() || dtor->hasBody()) { + auto cxxRecord = dtor->getParent(); - for (auto field : cxxRecord->fields()) { - if (auto fieldCxxRecord = field->getType()->getAsCXXRecordDecl()) - if (auto *fieldDtor = fieldCxxRecord->getDestructor()) - callback(fieldDtor); - } + for (auto field : cxxRecord->fields()) { + if (auto fieldCxxRecord = field->getType()->getAsCXXRecordDecl()) + if (auto *fieldDtor = fieldCxxRecord->getDestructor()) + callback(fieldDtor); + } - for (auto base : cxxRecord->bases()) { - if (auto baseCxxRecord = base.getType()->getAsCXXRecordDecl()) - if (auto *baseDtor = baseCxxRecord->getDestructor()) - callback(baseDtor); + for (auto base : cxxRecord->bases()) { + if (auto baseCxxRecord = base.getType()->getAsCXXRecordDecl()) + if (auto *baseDtor = baseCxxRecord->getDestructor()) + callback(baseDtor); + } } } diff --git a/test/Interop/Cxx/class/delete-operator-destructor-ref-irgen.swift b/test/Interop/Cxx/class/delete-operator-destructor-ref-irgen.swift index 2ea7d329ce094..312b23de51edf 100644 --- a/test/Interop/Cxx/class/delete-operator-destructor-ref-irgen.swift +++ b/test/Interop/Cxx/class/delete-operator-destructor-ref-irgen.swift @@ -33,6 +33,29 @@ private: BaseClass *pointer; }; +class ForwardClassDecl; + +template +class ContainerWithForward { +public: + inline ~ContainerWithForward() { + if (sizeof(T) > 0) + referencedSymbol(); + } +}; + +class ClassWithOutOfLineDestructor { +public: + ~ClassWithOutOfLineDestructor(); + + ContainerWithForward field; +}; + +ClassWithOutOfLineDestructor *getClassWithOutOfLineDestructorValue(); + +inline void testMethodDestructorFwdDecl() { + delete getClassWithOutOfLineDestructorValue(); +} //--- test.swift @@ -41,6 +64,7 @@ import DestroyedUsingDelete public func test() { let i = Container() i.method() + testMethodDestructorFwdDecl() } // Make sure we reach destructor accessible from `delete` statement.