summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCXX.cpp42
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h7
3 files changed, 49 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index bce22e5ec36..8c960c7f985 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -489,7 +489,7 @@ const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D,
/// base classes and non-static data members belonging to this constructor.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
- assert(ClassDecl->vbases_begin() == ClassDecl->vbases_end()
+ assert(!ClassDecl->isPolymorphic()
&& "FIXME. virtual base initialization unsupported");
for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
@@ -538,3 +538,43 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
}
}
}
+
+/// EmitDtorEpilogue - Emit all code that comes at the end of class's
+/// destructor. This is to call destructors on members and base classes
+/// in reverse order of their construction.
+void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD) {
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DD->getDeclContext());
+ assert(!ClassDecl->isPolymorphic() &&
+ "FIXME. polymorphic destruction not supported");
+ (void)ClassDecl; // prevent warning.
+
+ for (CXXDestructorDecl::destr_const_iterator *B = DD->destr_begin(),
+ *E = DD->destr_end(); B != E; ++B) {
+ uintptr_t BaseOrMember = (*B);
+ if (DD->isMemberToDestroy(BaseOrMember)) {
+ FieldDecl *FD = DD->getMemberToDestroy(BaseOrMember);
+ QualType FieldType = getContext().getCanonicalType((FD)->getType());
+ assert(!getContext().getAsArrayType(FieldType)
+ && "FIXME. Field arrays destruction unsupported");
+ const RecordType *RT = FieldType->getAs<RecordType>();
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (FieldClassDecl->hasTrivialDestructor())
+ continue;
+ llvm::Value *LoadOfThis = LoadCXXThis();
+ LValue LHS = EmitLValueForField(LoadOfThis, FD, false, 0);
+ EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()),
+ Dtor_Complete, LHS.getAddress());
+ }
+ else {
+ const RecordType *RT =
+ DD->getAnyBaseClassToDestroy(BaseOrMember)->getAs<RecordType>();
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (BaseClassDecl->hasTrivialDestructor())
+ continue;
+ llvm::Value *V = AddressCXXOfBaseClass(LoadCXXThis(),
+ ClassDecl,BaseClassDecl);
+ EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()),
+ Dtor_Complete, V);
+ }
+ }
+}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 82ec1eb603f..fb4b924765d 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -234,6 +234,8 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD))
EmitCtorPrologue(CD);
EmitStmt(S);
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD))
+ EmitDtorEpilogue(DD);
FinishFunction(S->getRBracLoc());
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index a3e37963104..4f8a14af142 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -359,7 +359,12 @@ public:
void FinishFunction(SourceLocation EndLoc=SourceLocation());
void EmitCtorPrologue(const CXXConstructorDecl *CD);
-
+
+ /// EmitDtorEpilogue - Emit all code that comes at the end of class's
+ /// destructor. This is to call destructors on members and base classes
+ /// in reverse order of their construction.
+ void EmitDtorEpilogue(const CXXDestructorDecl *DD);
+
/// EmitFunctionProlog - Emit the target specific LLVM code to load the
/// arguments for the given function. This is also responsible for naming the
/// LLVM function arguments.
OpenPOWER on IntegriCloud