aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaDeclCXX.cpp24
-rw-r--r--test/CXX/special/class.copy/p9.cpp44
2 files changed, 61 insertions, 7 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 4b7015caec..d710321939 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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
index 0000000000..d03794420e
--- /dev/null
+++ b/test/CXX/special/class.copy/p9.cpp
@@ -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}}
+}