diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-08-13 21:09:41 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-08-13 21:09:41 +0000 |
commit | ad25883a644dd6b52c7923dd128a7d05fb26213c (patch) | |
tree | 20af1f5012931dcbb928e97f8277f6bb6196a940 /lib/CodeGen | |
parent | 65010da986b2b13fa04c736855ac68183596420e (diff) |
Patch to force synthesis of copy assignment operator
function in the order according to c++03. ir-gen
for copy assignment in the trivial case and the first
test case.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78938 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 47 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 1 |
3 files changed, 55 insertions, 5 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 0f33c7b6fd..d1e8556160 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -228,6 +228,18 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, assert(MD->isInstance() && "Trying to emit a member call expr on a static method!"); + if (MD->isCopyAssignment()) { + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MD->getDeclContext()); + if (ClassDecl->hasTrivialCopyAssignment()) { + assert(!ClassDecl->hasUserDeclaredCopyAssignment() && + "EmitCXXOperatorMemberCallExpr - user declared copy assignment"); + llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); + llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress(); + QualType Ty = E->getType(); + EmitAggregateCopy(This, Src, Ty); + return RValue::get(This); + } + } const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); const llvm::Type *Ty = diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 22737a4d93..a99bae1799 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -653,11 +653,9 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, else if (!ClassDecl->hasUserDeclaredConstructor()) DeferredDeclsToEmit.push_back(D); } - else - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) - if (MD->isCopyAssignment()) { - DeferredDeclsToEmit.push_back(D); - } + else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) + if (MD->isCopyAssignment()) + DeferredCopyAssignmentToEmit(D); } // This function doesn't have a complete type (for example, the return @@ -718,7 +716,46 @@ void CodeGenModule::DeferredCopyConstructorToEmit(GlobalDecl CopyCtorDecl) { } } DeferredDeclsToEmit.push_back(CopyCtorDecl); +} + +/// Defer definition of copy assignments which need be implicitly defined. +void CodeGenModule::DeferredCopyAssignmentToEmit(GlobalDecl CopyAssignDecl) { + const CXXMethodDecl *CD = cast<CXXMethodDecl>(CopyAssignDecl.getDecl()); + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); + if (ClassDecl->hasTrivialCopyAssignment() || + ClassDecl->hasUserDeclaredCopyAssignment()) + return; + + // First make sure all direct base classes and virtual bases and non-static + // data mebers which need to have their copy assignments implicitly defined + // are defined. 12.8.p12 + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + const CXXMethodDecl *MD = 0; + if (BaseClassDecl->hasConstCopyAssignment(getContext(), MD)) + GetAddrOfFunction(GlobalDecl(MD), 0); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = Context.getCanonicalType((*Field)->getType()); + if (const ArrayType *Array = Context.getAsArrayType(FieldType)) + FieldType = Array->getElementType(); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + if ((*Field)->isAnonymousStructOrUnion()) + continue; + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + const CXXMethodDecl *MD = 0; + if (FieldClassDecl->hasConstCopyAssignment(getContext(), MD)) + GetAddrOfFunction(GlobalDecl(MD), 0); + } + } + DeferredDeclsToEmit.push_back(CopyAssignDecl); } /// GetAddrOfFunction - Return the address of the given function. If Ty is diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 449d29cc0d..8f69df51a5 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -398,6 +398,7 @@ private: const llvm::PointerType *PTy, const VarDecl *D); void DeferredCopyConstructorToEmit(GlobalDecl D); + void DeferredCopyAssignmentToEmit(GlobalDecl D); /// SetCommonAttributes - Set attributes which are common to any /// form of a global definition (alias, Objective-C method, |