aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-11-28 06:23:12 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-11-28 06:23:12 +0000
commitacf796b4797c5b3e9e237148fa622afdc04b3eff (patch)
tree6c271132920ce500bffd5b7d570b9f537eba17ac /lib/Sema/SemaDeclCXX.cpp
parent3881866dc782c5e13b21031bd363e93fbf367167 (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.cpp145
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);