]> granicus.if.org Git - clang/commitdiff
Handle references correctly when synthesizing copy constructors.
authorAnders Carlsson <andersca@mac.com>
Tue, 24 Nov 2009 21:08:10 +0000 (21:08 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 24 Nov 2009 21:08:10 +0000 (21:08 +0000)
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! :)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89799 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXX.cpp
test/CodeGenCXX/copy-constructor-synthesis.cpp

index 19cc04bace2960bcf2632cc792d7a713b50f5402..e1b673933907d346fe96d9df71de4b8a50877445 100644 (file)
@@ -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());
index 3b8f7821abcf3a2162f0ab0498f97bfe566200ce..2e950eb9e9b2f4cee9f7b8c7b8b189d238cde9a4 100644 (file)
@@ -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_: