зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
ae87ce7101
Коммит
393612e6c7
|
@ -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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче