diff options
author | Anders Carlsson <andersca@mac.com> | 2009-11-24 21:08:10 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-11-24 21:08:10 +0000 |
commit | 3c9beab48a6af525b851bfc44b55ddb2b35c5237 (patch) | |
tree | 18344234f5f8f0b3ab87af80a64ec98351a5653f | |
parent | 45b1a47a9cf7bda4dcee3b382f8069ca13ef08b6 (diff) | |
download | bcm5719-llvm-3c9beab48a6af525b851bfc44b55ddb2b35c5237.tar.gz bcm5719-llvm-3c9beab48a6af525b851bfc44b55ddb2b35c5237.zip |
Handle references correctly when synthesizing copy constructors.
With this change, the clang-on-clang test result is now
Expected Passes : 224
Unexpected Failures: 37
Which means that we can compile over 80% of clang with clang! :)
llvm-svn: 89799
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 36 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/copy-constructor-synthesis.cpp | 11 |
2 files changed, 39 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 19cc04bace2..e1b67393390 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -1366,10 +1366,11 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, Base->getType()); } - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - FieldEnd = ClassDecl->field_end(); - Field != FieldEnd; ++Field) { - QualType FieldType = getContext().getCanonicalType((*Field)->getType()); + for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), + E = ClassDecl->field_end(); I != E; ++I) { + const FieldDecl *Field = *I; + + QualType FieldType = getContext().getCanonicalType(Field->getType()); const ConstantArrayType *Array = getContext().getAsConstantArrayType(FieldType); if (Array) @@ -1378,8 +1379,8 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); - LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); - LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); + LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, Field, false, 0); if (Array) { const llvm::Type *BasePtr = ConvertType(FieldType); BasePtr = llvm::PointerType::getUnqual(BasePtr); @@ -1395,9 +1396,28 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, 0 /*ClassDecl*/, FieldClassDecl, FieldType); continue; } + + if (Field->getType()->isReferenceType()) { + unsigned FieldIndex = CGM.getTypes().getLLVMFieldNo(Field); + + llvm::Value *LHS = Builder.CreateStructGEP(LoadOfThis, FieldIndex, + "lhs.ref"); + + llvm::Value *RHS = Builder.CreateStructGEP(LoadOfThis, FieldIndex, + "rhs.ref"); + + // Load the value in RHS. + RHS = Builder.CreateLoad(RHS); + + // And store it in the LHS + Builder.CreateStore(RHS, LHS); + + continue; + } // Do a built-in assignment of scalar data members. - LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); - LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); + LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, Field, false, 0); + if (!hasAggregateLLVMType(Field->getType())) { RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType()); EmitStoreThroughLValue(RVRHS, LHS, Field->getType()); diff --git a/clang/test/CodeGenCXX/copy-constructor-synthesis.cpp b/clang/test/CodeGenCXX/copy-constructor-synthesis.cpp index 3b8f7821abc..2e950eb9e9b 100644 --- a/clang/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/clang/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -102,6 +102,17 @@ int main() { m1.pr(); } +struct A { +}; + +struct B : A { + A &a; +}; + +void f(const B &b1) { + B b2(b1); +} + // CHECK-LP64: .globl __ZN1XC1ERKS_ // CHECK-LP64: .weak_definition __ZN1XC1ERKS_ // CHECK-LP64: __ZN1XC1ERKS_: |