From: Douglas Gregor Date: Thu, 1 Jul 2010 18:27:03 +0000 (+0000) Subject: Teach DeclareImplicitCopyConstructor how to cope with virtual bases X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=598a8543ec4c22e7f0a27e7ff2cf7e49cfa4e4ff;p=clang Teach DeclareImplicitCopyConstructor how to cope with virtual bases 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 --- 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(Base->getType()->getAs()->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(Base->getType()->getAs()->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()) { const CXXRecordDecl *FieldClassDecl - = cast(FieldClassType->getDecl()); + = cast(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}} +}