forked from OSchip/llvm-project
Patch to instantiate destructors used to destruct
base and data members when they are needed. llvm-svn: 80967
This commit is contained in:
parent
92291f6ad0
commit
37d065680b
|
@ -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) {
|
||||
|
|
|
@ -522,67 +522,6 @@ CXXDestructorDecl::Destroy(ASTContext& C) {
|
|||
CXXMethodDecl::Destroy(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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue