diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 115 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 5 |
3 files changed, 109 insertions, 13 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 61ff4807b2..655f6f808d 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -1193,9 +1193,30 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { } } - if (!CD->isTrivial() && CD->getNumBaseOrMemberInitializers() == 0) + if (!CD->getNumBaseOrMemberInitializers() && !CD->isTrivial()) { // Nontrivial default constructor with no initializer list. It may still - // contain non-static data members which require construction. + // have bases classes and/or contain non-static data members which require + // construction. + for (CXXRecordDecl::base_class_const_iterator Base = + ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + // FIXME. copy assignment of virtual base NYI + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (BaseClassDecl->hasTrivialConstructor()) + continue; + if (CXXConstructorDecl *BaseCX = + BaseClassDecl->getDefaultConstructor(getContext())) { + LoadOfThis = LoadCXXThis(); + llvm::Value *V = AddressCXXOfBaseClass(LoadOfThis, ClassDecl, + BaseClassDecl); + EmitCXXConstructorCall(BaseCX, Ctor_Complete, V, 0, 0); + } + } + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), FieldEnd = ClassDecl->field_end(); Field != FieldEnd; ++Field) { @@ -1203,19 +1224,19 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { if (!FieldType->getAs<RecordType>() || Field->isAnonymousStructOrUnion()) continue; const RecordType *ClassRec = FieldType->getAs<RecordType>(); - if (CXXRecordDecl *MemberClassDecl = - dyn_cast<CXXRecordDecl>(ClassRec->getDecl())) { - if (MemberClassDecl->hasTrivialConstructor()) - continue; - if (CXXConstructorDecl *MamberCX = - MemberClassDecl->getDefaultConstructor(getContext())) { - LoadOfThis = LoadCXXThis(); - LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); - EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(), 0, 0); - } + CXXRecordDecl *MemberClassDecl = + dyn_cast<CXXRecordDecl>(ClassRec->getDecl()); + if (!MemberClassDecl || MemberClassDecl->hasTrivialConstructor()) + continue; + if (CXXConstructorDecl *MamberCX = + MemberClassDecl->getDefaultConstructor(getContext())) { + LoadOfThis = LoadCXXThis(); + LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); + EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(), 0, 0); } } - + } + // Initialize the vtable pointer if (ClassDecl->isDynamicClass()) { if (!LoadOfThis) @@ -1267,4 +1288,72 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD) { Dtor_Complete, V); } } + if (DD->getNumBaseOrMemberDestructions() || DD->isTrivial()) + return; + // Case of destructor synthesis with fields and base classes + // which have non-trivial destructors. They must be destructed in + // reverse order of their construction. + llvm::SmallVector<FieldDecl *, 16> DestructedFields; + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = getContext().getCanonicalType((*Field)->getType()); + // FIXME. Assert on arrays for now. + if (const RecordType *RT = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->hasTrivialDestructor()) + continue; + DestructedFields.push_back(*Field); + } + } + if (!DestructedFields.empty()) + for (int i = DestructedFields.size() -1; i >= 0; --i) { + FieldDecl *Field = DestructedFields[i]; + QualType FieldType = Field->getType(); + const RecordType *RT = FieldType->getAs<RecordType>(); + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + llvm::Value *LoadOfThis = LoadCXXThis(); + LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); + EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), + Dtor_Complete, LHS.getAddress()); + } + + llvm::SmallVector<CXXRecordDecl*, 4> DestructedBases; + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + // FIXME. copy assignment of virtual base NYI + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + DestructedBases.push_back(BaseClassDecl); + } + if (DestructedBases.empty()) + return; + for (int i = DestructedBases.size() -1; i >= 0; --i) { + CXXRecordDecl *BaseClassDecl = DestructedBases[i]; + llvm::Value *V = AddressCXXOfBaseClass(LoadCXXThis(), + ClassDecl,BaseClassDecl); + EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), + Dtor_Complete, V); + } } + +void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *CD, + const FunctionDecl *FD, + llvm::Function *Fn, + const FunctionArgList &Args) { + + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); + assert(!ClassDecl->hasUserDeclaredDestructor() && + "SynthesizeDefaultDestructor - destructor has user declaration"); + (void) ClassDecl; + + StartFunction(FD, FD->getResultType(), Fn, Args, SourceLocation()); + EmitDtorEpilogue(CD); + FinishFunction(); +} diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 1e8d05261d..d0c722ecfb 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -254,6 +254,8 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD, SynthesizeDefaultConstructor(CD, FD, Fn, Args); } } + else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) + SynthesizeDefaultDestructor(DD, FD, Fn, Args); else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) if (MD->isCopyAssignment()) SynthesizeCXXCopyAssignment(MD, FD, Fn, Args); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index c41af94e20..e2aba1b2ba 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -403,6 +403,11 @@ public: llvm::Function *Fn, const FunctionArgList &Args); + void SynthesizeDefaultDestructor(const CXXDestructorDecl *CD, + const FunctionDecl *FD, + llvm::Function *Fn, + const FunctionArgList &Args); + /// 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. |