]> granicus.if.org Git - clang/commitdiff
Teach DeclareImplicitCopyConstructor how to cope with virtual bases
authorDouglas Gregor <dgregor@apple.com>
Thu, 1 Jul 2010 18:27:03 +0000 (18:27 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 1 Jul 2010 18:27:03 +0000 (18:27 +0000)
and multi-dimensional array fields. Fixes several bugs found by
inspection.

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

lib/Sema/SemaDeclCXX.cpp
test/CXX/special/class.copy/p9.cpp [new file with mode: 0644]

index 4b7015caec57281a47989b24f7d5c0b2e86a5c81..d7103219393b4cd0d434b0cbe3f9f211967111ec 100644 (file)
@@ -4915,8 +4915,6 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(Scope *S,
   //   If the class definition does not explicitly declare a copy
   //   constructor, one is declared implicitly.
   
-  // FIXME: virtual bases!
-  
   // C++ [class.copy]p5:
   //   The implicitly-declared copy constructor for a class X will
   //   have the form
@@ -4933,6 +4931,20 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(Scope *S,
                                        BaseEnd = ClassDecl->bases_end();
        HasConstCopyConstructor && Base != BaseEnd; 
        ++Base) {
+    // Virtual bases are handled below.
+    if (Base->isVirtual())
+      continue;
+    
+    const CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    HasConstCopyConstructor
+      = BaseClassDecl->hasConstCopyConstructor(Context);
+  }
+
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+                                       BaseEnd = ClassDecl->vbases_end();
+       HasConstCopyConstructor && Base != BaseEnd; 
+       ++Base) {
     const CXXRecordDecl *BaseClassDecl
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
     HasConstCopyConstructor
@@ -4947,14 +4959,12 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(Scope *S,
                                   FieldEnd = ClassDecl->field_end();
        HasConstCopyConstructor && Field != FieldEnd;
        ++Field) {
-    QualType FieldType = (*Field)->getType();
-    if (const ArrayType *Array = Context.getAsArrayType(FieldType))
-      FieldType = Array->getElementType();
+    QualType FieldType = Context.getBaseElementType((*Field)->getType());
     if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
       const CXXRecordDecl *FieldClassDecl
-      = cast<CXXRecordDecl>(FieldClassType->getDecl());
+        = cast<CXXRecordDecl>(FieldClassType->getDecl());
       HasConstCopyConstructor
-      = FieldClassDecl->hasConstCopyConstructor(Context);
+        = FieldClassDecl->hasConstCopyConstructor(Context);
     }
   }
   
diff --git a/test/CXX/special/class.copy/p9.cpp b/test/CXX/special/class.copy/p9.cpp
new file mode 100644 (file)
index 0000000..d037944
--- /dev/null
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct ConstCopy {
+  ConstCopy();
+  ConstCopy(const ConstCopy&);
+};
+
+struct NonConstCopy {
+  NonConstCopy();
+  NonConstCopy(NonConstCopy&);
+};
+
+struct VirtualInheritsNonConstCopy : virtual NonConstCopy { 
+  VirtualInheritsNonConstCopy();
+  VirtualInheritsNonConstCopy(const VirtualInheritsNonConstCopy&);
+};
+
+struct ImplicitNonConstCopy1 : NonConstCopy { 
+  ImplicitNonConstCopy1();
+};
+
+struct ImplicitNonConstCopy2 {
+  ImplicitNonConstCopy2();
+  NonConstCopy ncc;
+};
+
+struct ImplicitNonConstCopy3 { 
+  ImplicitNonConstCopy3();
+  NonConstCopy ncc_array[2][3];
+};
+
+struct ImplicitNonConstCopy4 : VirtualInheritsNonConstCopy { 
+  ImplicitNonConstCopy4();
+};
+
+void test_non_const_copy(const ImplicitNonConstCopy1 &cincc1,
+                         const ImplicitNonConstCopy2 &cincc2,
+                         const ImplicitNonConstCopy3 &cincc3,
+                         const ImplicitNonConstCopy4 &cincc4) {
+  (void)sizeof(ImplicitNonConstCopy1(cincc1)); // expected-error{{functional-style cast from 'ImplicitNonConstCopy1 const' to 'ImplicitNonConstCopy1' is not allowed}}
+  (void)sizeof(ImplicitNonConstCopy2(cincc2)); // expected-error{{functional-style cast from 'ImplicitNonConstCopy2 const' to 'ImplicitNonConstCopy2' is not allowed}}
+  (void)sizeof(ImplicitNonConstCopy3(cincc3)); // expected-error{{functional-style cast from 'ImplicitNonConstCopy3 const' to 'ImplicitNonConstCopy3' is not allowed}}
+  (void)sizeof(ImplicitNonConstCopy4(cincc4)); // expected-error{{functional-style cast from 'ImplicitNonConstCopy4 const' to 'ImplicitNonConstCopy4' is not allowed}}
+}