[cfe-commits] r79269 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/default-destructor-synthesis.cpp
Fariborz Jahanian
fjahanian at apple.com
Mon Aug 17 12:04:51 PDT 2009
Author: fjahanian
Date: Mon Aug 17 14:04:50 2009
New Revision: 79269
URL: http://llvm.org/viewvc/llvm-project?rev=79269&view=rev
Log:
Patch to 1) synthesizing non-trivial default destructor when
one is not provided by user. 2) More complete
emission of ctor prologue when it has no initializer
list or when it is synthesized.
Added:
cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp
Modified:
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=79269&r1=79268&r2=79269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Mon Aug 17 14:04:50 2009
@@ -1193,9 +1193,30 @@
}
}
- 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 @@
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 @@
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();
+}
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=79269&r1=79268&r2=79269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Mon Aug 17 14:04:50 2009
@@ -254,6 +254,8 @@
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);
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=79269&r1=79268&r2=79269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Aug 17 14:04:50 2009
@@ -403,6 +403,11 @@
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.
Added: cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp?rev=79269&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/default-destructor-synthesis.cpp Mon Aug 17 14:04:50 2009
@@ -0,0 +1,54 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t-64.s &&
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -O0 -S %s -o %t-32.s &&
+// RUN: FileCheck -check-prefix LP32 -input-file=%t-32.s %s &&
+// RUN: true
+
+extern "C" int printf(...);
+
+struct S {
+ S() : iS(1), fS(1.23) {};
+ ~S(){printf("S::~S(%d, %f)\n", iS, fS); };
+ int iS;
+ float fS;
+};
+
+struct Q {
+ Q() : iQ(2), dQ(2.34) {};
+ ~Q(){printf("Q::~Q(%d, %f)\n", iQ, dQ); };
+ int iQ;
+ double dQ;
+};
+
+struct P {
+ P() : fP(3.45) , iP(3) {};
+ ~P(){printf("P::~P(%d, %f)\n", iP, fP); };
+ float fP;
+ int iP;
+};
+
+struct M : Q, P {
+ S s;
+
+ Q q;
+
+ P p;
+
+};
+
+M gm;
+
+int main() {M m1;}
+
+// CHECK-LP64: call __ZN1MC1Ev
+// CHECK-LP64: call __ZN1MD1Ev
+// CHECK-LP64: .globl __ZN1MD1Ev
+// CHECK-LP64-NEXT: .weak_definition __ZN1MD1Ev
+// CHECK-LP64-NEXT: __ZN1MD1Ev:
+
+
+// CHECK-LP32: call L__ZN1MC1Ev
+// CHECK-LP32: call L__ZN1MD1Ev
+// CHECK-LP32: .globl __ZN1MD1Ev
+// CHECK-LP32-NEXT: .weak_definition __ZN1MD1Ev
+// CHECK-LP32-NEXT: __ZN1MD1Ev:
More information about the cfe-commits
mailing list