diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-09-03 23:18:17 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-09-03 23:18:17 +0000 |
commit | 34374e6ce5710a91c478f69379220ff20c3e7f15 (patch) | |
tree | c8ba1e3883eafe3528fd4e84a04f1a5310f76a07 | |
parent | 366200045fc30290795e037ab2cb417ddd3c9933 (diff) |
Patch to instantiate destructors used to destruct
base and data members when they are needed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80967 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/DeclCXX.h | 25 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 61 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 75 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 4 | ||||
-rw-r--r-- | test/CodeGenCXX/constructor-template.cpp | 7 |
7 files changed, 109 insertions, 71 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 37666d4c75..ce6e925a9a 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1095,12 +1095,13 @@ public: /// }; /// @endcode class CXXDestructorDecl : public CXXMethodDecl { +public: enum KindOfObjectToDestroy { VBASE = 0x1, DRCTNONVBASE = 0x2, ANYBASE = 0x3 }; - +private: /// ImplicitlyDefined - Whether this destructor was implicitly /// defined by the compiler. When false, the destructor was defined /// by the user. In C++03, this flag will have the same value as @@ -1181,12 +1182,24 @@ public: return NumBaseOrMemberDestructions; } - /// getBaseOrMember - get the generic 'member' representing either the field - /// or a base class. + /// setNumBaseOrMemberDestructions - Set number of base and non-static members + /// to destroy. + void setNumBaseOrMemberDestructions(unsigned numBaseOrMemberDestructions) { + NumBaseOrMemberDestructions = numBaseOrMemberDestructions; + } + + /// getBaseOrMemberToDestroy - get the generic 'member' representing either + /// the field or a base class. uintptr_t* getBaseOrMemberToDestroy() const { return BaseOrMemberDestructions; } + /// setBaseOrMemberToDestroy - set the generic 'member' representing either + /// the field or a base class. + void setBaseOrMemberDestructions(uintptr_t* baseOrMemberDestructions) { + BaseOrMemberDestructions = baseOrMemberDestructions; + } + /// isVbaseToDestroy - returns true, if object is virtual base. bool isVbaseToDestroy(uintptr_t Vbase) const { return (Vbase & VBASE) != 0; @@ -1229,12 +1242,6 @@ public: return reinterpret_cast<Type*>(Base & ~0x02); return 0; } - - /// computeBaseOrMembersToDestroy - Compute information in current - /// destructor decl's AST of bases and non-static data members which will be - /// implicitly destroyed. We are storing the destruction in the order that - /// they should occur (which is the reverse of construction order). - void computeBaseOrMembersToDestroy(ASTContext &C); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 036752f5ca..29a7c7fad9 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -523,67 +523,6 @@ CXXDestructorDecl::Destroy(ASTContext& C) { } void -CXXDestructorDecl::computeBaseOrMembersToDestroy(ASTContext &C) { - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(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; - uintptr_t Member = - reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr()) | 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; - - uintptr_t Member = - reinterpret_cast<uintptr_t>(Base->getType().getTypePtr()) | 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 = C.getBaseElementType((*Field)->getType()); - - if (const RecordType* RT = FieldType->getAs<RecordType>()) { - // Skip over virtual bases which have trivial destructors. - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); - if (BaseClassDecl->hasTrivialDestructor()) - continue; - uintptr_t Member = reinterpret_cast<uintptr_t>(*Field); - AllToDestruct.push_back(Member); - } - } - - unsigned NumDestructions = AllToDestruct.size(); - if (NumDestructions > 0) { - NumBaseOrMemberDestructions = NumDestructions; - BaseOrMemberDestructions = new (C) uintptr_t [NumDestructions]; - // Insert in reverse order. - for (int Idx = NumDestructions-1, i=0 ; Idx >= 0; --Idx) - BaseOrMemberDestructions[i++] = AllToDestruct[Idx]; - } -} - -void CXXConstructorDecl::Destroy(ASTContext& C) { C.Deallocate(BaseOrMemberInitializers); CXXMethodDecl::Destroy(C); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 766d18bde1..746c28af62 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2191,6 +2191,12 @@ public: llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, llvm::SmallVectorImpl<FieldDecl *>&Members); + /// computeBaseOrMembersToDestroy - Compute information in current + /// destructor decl's AST of bases and non-static data members which will be + /// implicitly destroyed. We are storing the destruction in the order that + /// they should occur (which is the reverse of construction order). + void computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor); + void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e7a327805a..abf95283cd 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3758,7 +3758,7 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body)); if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) - Destructor->computeBaseOrMembersToDestroy(Context); + computeBaseOrMembersToDestroy(Destructor); return D; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 075c945456..e5a4c6f81a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/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; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index b88ee89752..c62159d001 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -757,6 +757,10 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, &DeleteArg, 1, Record, /*AllowMissing=*/true, OperatorDelete)) return ExprError(); + if (!Record->hasTrivialDestructor()) + if (const CXXDestructorDecl *Dtor = Record->getDestructor(Context)) + MarkDeclarationReferenced(StartLoc, + const_cast<CXXDestructorDecl*>(Dtor)); } if (!OperatorDelete) { diff --git a/test/CodeGenCXX/constructor-template.cpp b/test/CodeGenCXX/constructor-template.cpp index 5fc6c2dfab..84e77d43da 100644 --- a/test/CodeGenCXX/constructor-template.cpp +++ b/test/CodeGenCXX/constructor-template.cpp @@ -22,12 +22,14 @@ struct B { template <typename T> class List { public: List(){ } // List<BinomialNode<int>*>::List() remains undefined. + ~List() {} }; template <typename T> class Node { int i; public: Node(){ } // Node<BinomialNode<int>*>::Node() remains undefined. + ~Node() {} }; @@ -40,10 +42,15 @@ public: int main() { B<int> *n = new B<int>(4); BinomialNode<int> *node = new BinomialNode<int>(1); + delete node; } +// CHECK-LP64: __ZN4ListIP12BinomialNodeIiEED1Ev: +// CHECK-LP64: __ZN4ListIP12BinomialNodeIiEED2Ev: // CHECK-LP64: __ZN4NodeIP12BinomialNodeIiEEC1Ev: // CHECK-LP64: __ZN4ListIP12BinomialNodeIiEEC1Ev: +// CHECK-LP32: __ZN4ListIP12BinomialNodeIiEED1Ev: +// CHECK-LP32: __ZN4ListIP12BinomialNodeIiEED2Ev: // CHECK-LP32: __ZN4NodeIP12BinomialNodeIiEEC1Ev: // CHECK-LP32: __ZN4ListIP12BinomialNodeIiEEC1Ev: |