Patch to accomodate Doug's comment on default

destruction of base/members for each destructor AST.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76663 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Fariborz Jahanian 2009-07-21 22:36:06 +00:00
Родитель ae87ce7101
Коммит 393612e6c7
9 изменённых файлов: 123 добавлений и 47 удалений

Просмотреть файл

@ -901,10 +901,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
/// Support for base and member destruction.
/// BaseOrMemberDestructions - The arguments used to destruct the base
/// or member.
// FIXME. May want to use a new class as CXXBaseOrMemberInitializer has
// more info. than is needed. At the least, CXXBaseOrMemberInitializer need
// be renamed to something neutral.
CXXBaseOrMemberInitializer **BaseOrMemberDestructions;
uintptr_t *BaseOrMemberDestructions;
unsigned NumBaseOrMemberDestructions;
CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
@ -915,7 +912,8 @@ class CXXDestructorDecl : public CXXMethodDecl {
BaseOrMemberDestructions(0), NumBaseOrMemberDestructions(0) {
setImplicit(isImplicitlyDeclared);
}
virtual void Destroy(ASTContext& C);
public:
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
@ -941,32 +939,88 @@ public:
}
/// destr_iterator - Iterates through the member/base destruction list.
typedef CXXBaseOrMemberInitializer **destr_iterator;
/// destr_const_iterator - Iterates through the member/base destruction list.
typedef CXXBaseOrMemberInitializer * const * destr_const_iterator;
typedef uintptr_t const destr_const_iterator;
/// destr_begin() - Retrieve an iterator to the first destructed member/base.
destr_iterator destr_begin() { return BaseOrMemberDestructions; }
uintptr_t* destr_begin() {
return BaseOrMemberDestructions;
}
/// destr_begin() - Retrieve an iterator to the first destructed member/base.
destr_const_iterator destr_begin() const { return BaseOrMemberDestructions; }
uintptr_t* destr_begin() const {
return BaseOrMemberDestructions;
}
/// destr_end() - Retrieve an iterator past the last destructed member/base.
destr_iterator destr_end() {
uintptr_t* destr_end() {
return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
}
/// destr_end() - Retrieve an iterator past the last destructed member/base.
destr_const_iterator destr_end() const {
uintptr_t* destr_end() const {
return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
}
/// getNumArgs - Determine the number of arguments used to
/// destruct the member or base.
/// getNumBaseOrMemberDestructions - Number of base and non-static members
/// to destroy.
unsigned getNumBaseOrMemberDestructions() const {
return NumBaseOrMemberDestructions;
}
void setBaseOrMemberDestructions(ASTContext &C);
/// getBaseOrMember - get the generic 'member' representing either the field
/// or a base class.
uintptr_t* getBaseOrMemberToDestroy() const {
return BaseOrMemberDestructions;
}
/// isVbaseToDestroy - returns true, if object is virtual base.
bool isVbaseToDestroy(uintptr_t Vbase) const {
return (Vbase & 0x1) != 0;
}
/// isDirectNonVBaseToDestroy - returns true, if object is direct non-virtual
/// base.
bool isDirectNonVBaseToDestroy(uintptr_t DrctNonVbase) const {
return (DrctNonVbase & 0x2) != 0;
}
/// isAnyBaseToDestroy - returns true, if object is any base (virtual or
/// direct non-virtual)
bool isAnyBaseToDestroy(uintptr_t AnyBase) const {
return (AnyBase & 0x3) != 0;
}
/// isMemberToDestroy - returns true if object is a non-static data member.
bool isMemberToDestroy(uintptr_t Member) const {
return (Member & 0x3) == 0;
}
/// getAnyBaseClassToDestroy - Get the type for the given base class object.
Type *getAnyBaseClassToDestroy(uintptr_t Base) const {
if (isAnyBaseToDestroy(Base))
return reinterpret_cast<Type*>(Base & ~0x03);
return 0;
}
/// getMemberToDestroy - Get the member for the given object.
FieldDecl *getMemberToDestroy(uintptr_t Member) {
if (isMemberToDestroy(Member))
return reinterpret_cast<FieldDecl *>(Member);
return 0;
}
/// getVbaseClassToDestroy - Get the virtual base.
Type *getVbaseClassToDestroy(uintptr_t Vbase) const {
if (isVbaseToDestroy(Vbase))
return reinterpret_cast<Type*>(Vbase & ~0x01);
return 0;
}
/// getDirectNonVBaseClassToDestroy - Get the virtual base.
Type *getDirectNonVBaseClassToDestroy(uintptr_t Base) const {
if (isDirectNonVBaseToDestroy(Base))
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) {

Просмотреть файл

@ -1233,7 +1233,7 @@ public:
MemInitTy **MemInits, unsigned NumMemInits){
}
virtual void ActOnDefaultCDtorInitializers(DeclPtrTy CDtorDecl) {}
virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {}
/// ActOnFinishCXXMemberSpecification - Invoked after all member declarators
/// are parsed but *before* parsing of inline method definitions.

Просмотреть файл

@ -480,13 +480,25 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
}
void
CXXDestructorDecl::setBaseOrMemberDestructions(ASTContext &C) {
CXXDestructorDecl::Destroy(ASTContext& C) {
C.Deallocate(BaseOrMemberDestructions);
CXXMethodDecl::Destroy(C);
}
void
CXXDestructorDecl::computeBaseOrMembersToDestroy(ASTContext &C) {
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(getDeclContext());
llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToDestruct;
llvm::SmallVector<uintptr_t, 32> AllToDestruct;
for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
CXXBaseOrMemberInitializer *Member =
new CXXBaseOrMemberInitializer(VBase->getType(), 0, 0,SourceLocation());
// Skip over virtual bases which have trivial destructors.
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(VBase->getType()->getAsRecordType()->getDecl());
if (BaseClassDecl->hasTrivialDestructor())
continue;
uintptr_t Member =
reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr()) | 0x1;
AllToDestruct.push_back(Member);
}
for (CXXRecordDecl::base_class_iterator Base =
@ -494,10 +506,17 @@ CXXDestructorDecl::setBaseOrMemberDestructions(ASTContext &C) {
E = ClassDecl->bases_end(); Base != E; ++Base) {
if (Base->isVirtual())
continue;
CXXBaseOrMemberInitializer *Member =
new CXXBaseOrMemberInitializer(Base->getType(), 0, 0, SourceLocation());
// Skip over virtual bases which have trivial destructors.
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
if (BaseClassDecl->hasTrivialDestructor())
continue;
uintptr_t Member =
reinterpret_cast<uintptr_t>(Base->getType().getTypePtr()) | 0x2;
AllToDestruct.push_back(Member);
}
// non-static data members.
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
E = ClassDecl->field_end(); Field != E; ++Field) {
@ -506,8 +525,12 @@ CXXDestructorDecl::setBaseOrMemberDestructions(ASTContext &C) {
FieldType = AT->getElementType();
if (FieldType->getAsRecordType()) {
CXXBaseOrMemberInitializer *Member =
new CXXBaseOrMemberInitializer((*Field), 0, 0, SourceLocation());
// Skip over virtual bases which have trivial destructors.
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(FieldType->getAsRecordType()->getDecl());
if (BaseClassDecl->hasTrivialDestructor())
continue;
uintptr_t Member = reinterpret_cast<uintptr_t>(*Field);
AllToDestruct.push_back(Member);
}
}
@ -515,8 +538,7 @@ CXXDestructorDecl::setBaseOrMemberDestructions(ASTContext &C) {
unsigned NumDestructions = AllToDestruct.size();
if (NumDestructions > 0) {
NumBaseOrMemberDestructions = NumDestructions;
BaseOrMemberDestructions =
new (C) CXXBaseOrMemberInitializer*[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];

Просмотреть файл

@ -376,25 +376,25 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
else if (CXXDestructorDecl *DDecl = dyn_cast<CXXDestructorDecl>(D)) {
if (DDecl->getNumBaseOrMemberDestructions() > 0) {
// FIXME. This is strictly for visualization of destructor's AST for
// how base/members are destructed. It has no other validity.
// List order of base/member destruction for visualization purposes.
assert (D->isThisDeclarationADefinition() && "Destructor with dtor-list");
Proto += " : ";
for (CXXDestructorDecl::destr_const_iterator B = DDecl->destr_begin(),
E = DDecl->destr_end();
Proto += "/* : ";
for (CXXDestructorDecl::destr_const_iterator *B = DDecl->destr_begin(),
*E = DDecl->destr_end();
B != E; ++B) {
CXXBaseOrMemberInitializer * BMInitializer = (*B);
uintptr_t BaseOrMember = (*B);
if (B != DDecl->destr_begin())
Proto += ", ";
if (BMInitializer->isMemberInitializer()) {
FieldDecl *FD = BMInitializer->getMember();
if (DDecl->isMemberToDestroy(BaseOrMember)) {
FieldDecl *FD = DDecl->getMemberToDestroy(BaseOrMember);
Proto += "~";
Proto += FD->getNameAsString();
}
else // FIXME. skip dependent types for now.
if (const RecordType *RT =
BMInitializer->getBaseClass()->getAsRecordType()) {
DDecl->getAnyBaseClassToDestroy(BaseOrMember)
->getAsRecordType()) {
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(RT->getDecl());
Proto += "~";
@ -402,6 +402,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
Proto += "()";
}
Proto += " */";
}
}
else

Просмотреть файл

@ -172,7 +172,7 @@ void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
if (Tok.is(tok::colon))
ParseConstructorInitializer(LM.D);
else
Actions.ActOnDefaultCDtorInitializers(LM.D);
Actions.ActOnDefaultCtorInitializers(LM.D);
// FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'??
ParseFunctionStatementBody(LM.D);

Просмотреть файл

@ -666,7 +666,7 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
if (Tok.is(tok::colon))
ParseConstructorInitializer(Res);
else
Actions.ActOnDefaultCDtorInitializers(Res);
Actions.ActOnDefaultCtorInitializers(Res);
return ParseFunctionStatementBody(Res);
}

Просмотреть файл

@ -1463,7 +1463,7 @@ public:
SourceLocation MemberLoc,
IdentifierInfo &Member,
DeclPtrTy ImplDecl);
virtual void ActOnDefaultCDtorInitializers(DeclPtrTy CDtorDecl);
virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl);
bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,

Просмотреть файл

@ -3282,12 +3282,15 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
// Verify that that gotos and switch cases don't jump into scopes illegally.
if (CurFunctionNeedsScopeChecking)
DiagnoseInvalidJumps(Body);
// C++ constructors that have function-try-blocks can't have return statements
// in the handlers of that block. (C++ [except.handle]p14) Verify this.
// C++ constructors that have function-try-blocks can't have return
// statements in the handlers of that block. (C++ [except.handle]p14)
// Verify this.
if (isa<CXXConstructorDecl>(dcl) && isa<CXXTryStmt>(Body))
DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl))
Destructor->computeBaseOrMembersToDestroy(Context);
return D;
}

Просмотреть файл

@ -918,7 +918,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
}
}
void Sema::ActOnDefaultCDtorInitializers(DeclPtrTy CDtorDecl) {
void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {
if (!CDtorDecl)
return;
@ -926,10 +926,6 @@ void Sema::ActOnDefaultCDtorInitializers(DeclPtrTy CDtorDecl) {
= dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
Constructor->setBaseOrMemberInitializers(Context,
(CXXBaseOrMemberInitializer **)0, 0);
else
if (CXXDestructorDecl *Destructor
= dyn_cast<CXXDestructorDecl>(CDtorDecl.getAs<Decl>()))
Destructor->setBaseOrMemberDestructions(Context);
}
namespace {