diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-11-28 06:23:12 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-11-28 06:23:12 +0000 |
commit | acf796b4797c5b3e9e237148fa622afdc04b3eff (patch) | |
tree | 6c271132920ce500bffd5b7d570b9f537eba17ac /lib/Sema/SemaDeclCXX.cpp | |
parent | 3881866dc782c5e13b21031bd363e93fbf367167 (diff) |
Store on the CXXRecordDecl whether the class has, or would have, a copy
constructor/assignment operator with a const-qualified parameter type. The
prior method for determining this incorrectly used overload resolution.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168775 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 145 |
1 files changed, 4 insertions, 141 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 86da9e907b..b8056795e9 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4193,9 +4193,6 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) CanonicalFPT, ExceptSpec); } -static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl *ClassDecl); -static bool isImplicitCopyAssignmentArgConst(Sema &S, CXXRecordDecl *ClassDecl); - void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { CXXRecordDecl *RD = MD->getParent(); CXXSpecialMember CSM = getSpecialMember(MD); @@ -4238,11 +4235,11 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { Trivial = RD->hasTrivialDefaultConstructor(); break; case CXXCopyConstructor: - CanHaveConstParam = isImplicitCopyCtorArgConst(*this, RD); + CanHaveConstParam = RD->implicitCopyConstructorHasConstParam(); Trivial = RD->hasTrivialCopyConstructor(); break; case CXXCopyAssignment: - CanHaveConstParam = isImplicitCopyAssignmentArgConst(*this, RD); + CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam(); Trivial = RD->hasTrivialCopyAssignment(); break; case CXXMoveConstructor: @@ -7727,76 +7724,6 @@ buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, return Result; } -/// Determine whether an implicit copy assignment operator for ClassDecl has a -/// const argument. -/// FIXME: It ought to be possible to store this on the record. -static bool isImplicitCopyAssignmentArgConst(Sema &S, - CXXRecordDecl *ClassDecl) { - if (ClassDecl->isInvalidDecl()) - return true; - - // C++ [class.copy]p10: - // If the class definition does not explicitly declare a copy - // assignment operator, one is declared implicitly. - // The implicitly-defined copy assignment operator for a class X - // will have the form - // - // X& X::operator=(const X&) - // - // if - // -- each direct base class B of X has a copy assignment operator - // whose parameter is of type const B&, const volatile B& or B, - // and - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), - BaseEnd = ClassDecl->bases_end(); - Base != BaseEnd; ++Base) { - // We'll handle this below - if (S.getLangOpts().CPlusPlus0x && Base->isVirtual()) - continue; - - assert(!Base->getType()->isDependentType() && - "Cannot generate implicit members for class with dependent bases."); - CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); - if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, false, 0)) - return false; - } - - // In C++11, the above citation has "or virtual" added - if (S.getLangOpts().CPlusPlus0x) { - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), - BaseEnd = ClassDecl->vbases_end(); - Base != BaseEnd; ++Base) { - assert(!Base->getType()->isDependentType() && - "Cannot generate implicit members for class with dependent bases."); - CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); - if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, - false, 0)) - return false; - } - } - - // -- for all the nonstatic data members of X that are of a class - // type M (or array thereof), each such class type has a copy - // assignment operator whose parameter is of type const M&, - // const volatile M& or M. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - FieldEnd = ClassDecl->field_end(); - Field != FieldEnd; ++Field) { - QualType FieldType = S.Context.getBaseElementType(Field->getType()); - if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) - if (!S.LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const, - false, 0)) - return false; - } - - // Otherwise, the implicitly declared copy assignment operator will - // have the form - // - // X& X::operator=(X&) - - return true; -} - Sema::ImplicitExceptionSpecification Sema::ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD) { CXXRecordDecl *ClassDecl = MD->getParent(); @@ -7868,7 +7795,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { QualType ArgType = Context.getTypeDeclType(ClassDecl); QualType RetType = Context.getLValueReferenceType(ArgType); - if (isImplicitCopyAssignmentArgConst(*this, ClassDecl)) + if (ClassDecl->implicitCopyAssignmentHasConstParam()) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); @@ -8580,70 +8507,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } } -/// Determine whether an implicit copy constructor for ClassDecl has a const -/// argument. -/// FIXME: It ought to be possible to store this on the record. -static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl *ClassDecl) { - if (ClassDecl->isInvalidDecl()) - return true; - - // C++ [class.copy]p5: - // The implicitly-declared copy constructor for a class X will - // have the form - // - // X::X(const X&) - // - // if - // -- each direct or virtual base class B of X has a copy - // constructor whose first parameter is of type const B& or - // const volatile B&, and - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), - BaseEnd = ClassDecl->bases_end(); - Base != BaseEnd; ++Base) { - // Virtual bases are handled below. - if (Base->isVirtual()) - continue; - - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - // FIXME: This lookup is wrong. If the copy ctor for a member or base is - // ambiguous, we should still produce a constructor with a const-qualified - // parameter. - if (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const)) - return false; - } - - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), - BaseEnd = ClassDecl->vbases_end(); - Base != BaseEnd; ++Base) { - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - if (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const)) - return false; - } - - // -- for all the nonstatic data members of X that are of a - // class type M (or array thereof), each such class type - // has a copy constructor whose first parameter is of type - // const M& or const volatile M&. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - FieldEnd = ClassDecl->field_end(); - Field != FieldEnd; ++Field) { - QualType FieldType = S.Context.getBaseElementType(Field->getType()); - if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { - if (!S.LookupCopyingConstructor(FieldClassDecl, Qualifiers::Const)) - return false; - } - } - - // Otherwise, the implicitly declared copy constructor will have - // the form - // - // X::X(X&) - - return true; -} - Sema::ImplicitExceptionSpecification Sema::ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD) { CXXRecordDecl *ClassDecl = MD->getParent(); @@ -8708,7 +8571,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( QualType ClassType = Context.getTypeDeclType(ClassDecl); QualType ArgType = ClassType; - bool Const = isImplicitCopyCtorArgConst(*this, ClassDecl); + bool Const = ClassDecl->implicitCopyConstructorHasConstParam(); if (Const) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); |