aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-08-07 20:22:40 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-08-07 20:22:40 +0000
commit97a937532c24a8ea44317d4fdee26d9701a1e83c (patch)
tree72bf23f715386546c2f1d1b30b34fc431011d31a /lib/CodeGen
parente6e1d609f6a14882be5336005f5d0222ef18b814 (diff)
More synthesis of copy constructors. Work in progress.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78402 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGCXX.cpp47
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp1
-rw-r--r--lib/CodeGen/CodeGenFunction.h2
-rw-r--r--lib/CodeGen/CodeGenModule.cpp47
-rw-r--r--lib/CodeGen/CodeGenModule.h1
5 files changed, 94 insertions, 4 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index d849336ff6..cb6a6f8271 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -652,6 +652,53 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
return vtable;
}
+/// EmitCopyCtorBody - This routine implicitly defines body of a copy
+/// constructor, in accordance with section 12.8 (p7 and p8) of C++03
+/// The implicitly-defined copy constructor for class X performs a memberwise
+/// copy of its subobjects. The order of copying is the same as the order
+/// of initialization of bases and members in a user-defined constructor
+/// Each subobject is copied in the manner appropriate to its type:
+/// if the subobject is of class type, the copy constructor for the class is
+/// used;
+/// if the subobject is an array, each element is copied, in the manner
+/// appropriate to the element type;
+/// if the subobject is of scalar type, the built-in assignment operator is
+/// used.
+/// Virtual base class subobjects shall be copied only once by the
+/// implicitly-defined copy constructor
+
+void CodeGenFunction::EmitCopyCtorBody(const CXXConstructorDecl *CD) {
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
+ assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
+ "EmitCopyCtorBody - copy constructor has definition already");
+
+ for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ // FIXME. copy constrution of virtual base NYI
+ if (Base->isVirtual())
+ continue;
+#if 0
+ unsigned TypeQuals;
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (CXXConstructorDecl *BaseCopyCtor =
+ BaseClassDecl->getCopyConstructor(getContext(), TypeQuals)) {
+
+ llvm::Value *LoadOfThis = LoadCXXThis();
+ llvm::Value *V = AddressCXXOfBaseClass(LoadOfThis, ClassDecl,
+ BaseClassDecl);
+ EmitCXXConstructorCall(BaseCopyCtor,
+ Ctor_Complete, V,
+ Member->const_arg_begin(),
+ Member->const_arg_end());
+
+ }
+#endif
+ }
+
+}
+
+
/// EmitCtorPrologue - This routine generates necessary code to initialize
/// base classes and non-static data members belonging to this constructor.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 0f155ec648..7c9b3af8d3 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -247,6 +247,7 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
"bogus constructor is being synthesize");
StartFunction(FD, FD->getResultType(), Fn, Args, SourceLocation());
+ EmitCopyCtorBody(CD);
FinishFunction();
}
else {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 63632f5f40..b512d3670b 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -369,6 +369,8 @@ public:
void EmitCtorPrologue(const CXXConstructorDecl *CD);
+ void EmitCopyCtorBody(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.
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 8e53651c8e..e1cf13c72d 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -645,10 +645,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
const CXXRecordDecl *ClassDecl =
cast<CXXRecordDecl>(CD->getDeclContext());
- if (CD->isCopyConstructor(getContext())) {
- if (!ClassDecl->hasUserDeclaredCopyConstructor())
- DeferredDeclsToEmit.push_back(D);
- }
+ if (CD->isCopyConstructor(getContext()))
+ DeferredCopyConstructorToEmit(D);
else if (!ClassDecl->hasUserDeclaredConstructor())
DeferredDeclsToEmit.push_back(D);
}
@@ -674,6 +672,47 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
return F;
}
+/// Defer definition of copy constructor(s) which need be implicitly defined.
+void CodeGenModule::DeferredCopyConstructorToEmit(GlobalDecl CopyCtorDecl) {
+ const CXXConstructorDecl *CD =
+ cast<CXXConstructorDecl>(CopyCtorDecl.getDecl());
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
+ if (ClassDecl->hasTrivialCopyConstructor() ||
+ ClassDecl->hasUserDeclaredCopyConstructor())
+ return;
+
+ // First make sure all direct base classes and virtual bases and non-static
+ // data mebers which need to have their copy constructors implicitly defined
+ // are defined. 12.8.p7
+ for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ unsigned TypeQuals;
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (CXXConstructorDecl *BaseCopyCtor =
+ BaseClassDecl->getCopyConstructor(Context, TypeQuals))
+ GetAddrOfCXXConstructor(BaseCopyCtor, Ctor_Complete);
+ }
+
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ Field != FieldEnd; ++Field) {
+ unsigned TypeQuals;
+ QualType FieldType = Context.getCanonicalType((*Field)->getType());
+ if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+ FieldType = Array->getElementType();
+ if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (CXXConstructorDecl *FieldCopyCtor =
+ FieldClassDecl->getCopyConstructor(Context, TypeQuals))
+ GetAddrOfCXXConstructor(FieldCopyCtor, Ctor_Complete);
+ }
+ }
+ DeferredDeclsToEmit.push_back(CopyCtorDecl);
+
+}
+
/// GetAddrOfFunction - Return the address of the given function. If Ty is
/// non-null, then this function will use the specified type if it has to
/// create it (this occurs when we see a definition of the function).
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 7c1108e801..3aa015a99f 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -393,6 +393,7 @@ private:
llvm::Constant *GetOrCreateLLVMGlobal(const char *MangledName,
const llvm::PointerType *PTy,
const VarDecl *D);
+ void DeferredCopyConstructorToEmit(GlobalDecl D);
/// SetCommonAttributes - Set attributes which are common to any
/// form of a global definition (alias, Objective-C method,