diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 075c9454560..e5a4c6f81a6 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1284,6 +1284,81 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, } } +void +Sema::computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor) { + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext()); + llvm::SmallVector<uintptr_t, 32> AllToDestruct; + + for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) { + if (VBase->getType()->isDependentType()) + continue; + // Skip over virtual bases which have trivial destructors. + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context)) + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); + + uintptr_t Member = + reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr()) + | CXXDestructorDecl::VBASE; + AllToDestruct.push_back(Member); + } + for (CXXRecordDecl::base_class_iterator Base = + ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + if (Base->isVirtual()) + continue; + if (Base->getType()->isDependentType()) + continue; + // Skip over virtual bases which have trivial destructors. + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context)) + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); + uintptr_t Member = + reinterpret_cast<uintptr_t>(Base->getType().getTypePtr()) + | CXXDestructorDecl::DRCTNONVBASE; + AllToDestruct.push_back(Member); + } + + // non-static data members. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + + if (const RecordType* RT = FieldType->getAs<RecordType>()) { + // Skip over virtual bases which have trivial destructors. + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->hasTrivialDestructor()) + continue; + if (const CXXDestructorDecl *Dtor = + FieldClassDecl->getDestructor(Context)) + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); + uintptr_t Member = reinterpret_cast<uintptr_t>(*Field); + AllToDestruct.push_back(Member); + } + } + + unsigned NumDestructions = AllToDestruct.size(); + if (NumDestructions > 0) { + Destructor->setNumBaseOrMemberDestructions(NumDestructions); + uintptr_t *BaseOrMemberDestructions = + new (Context) uintptr_t [NumDestructions]; + // Insert in reverse order. + for (int Idx = NumDestructions-1, i=0 ; Idx >= 0; --Idx) + BaseOrMemberDestructions[i++] = AllToDestruct[Idx]; + Destructor->setBaseOrMemberDestructions(BaseOrMemberDestructions); + } +} + void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) { if (!CDtorDecl) return; |

