From: Sean Hunt Date: Fri, 10 Jun 2011 04:44:37 +0000 (+0000) Subject: Implement caching for copy constructors in similar situations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c530d1758cef1acc596f2ec905665da534e66d29;p=clang Implement caching for copy constructors in similar situations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132835 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 32bd86252e..a1c0ba9dcf 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1669,6 +1669,9 @@ public: DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class); CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class); + CXXConstructorDecl *LookupCopyConstructor(CXXRecordDecl *Class, + unsigned Quals, + bool *ConstParam = 0); CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); void ArgumentDependentLookup(DeclarationName Name, bool Operator, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 29e81d3f7f..a4ba5fafea 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3481,12 +3481,13 @@ bool Sema::ShouldDeleteCopyConstructor(CXXConstructorDecl *CD) { // Do access control from the constructor ContextRAII CtorContext(*this, CD); - bool Union = RD->isUnion(); + bool Union = RD->isUnion(); assert(!CD->getParamDecl(0)->getType()->getPointeeType().isNull() && "copy assignment arg has no pointee type"); - bool ConstArg = - CD->getParamDecl(0)->getType()->getPointeeType().isConstQualified(); + unsigned ArgQuals = + CD->getParamDecl(0)->getType()->getPointeeType().isConstQualified() ? + Qualifiers::Const : 0; // We do this because we should never actually use an anonymous // union's constructor. @@ -3522,20 +3523,11 @@ bool Sema::ShouldDeleteCopyConstructor(CXXConstructorDecl *CD) { // resolution, as applied to B's [copy] constructor, results in an // ambiguity or a function that is deleted or inaccessible from the // defaulted constructor - InitializedEntity BaseEntity = - InitializedEntity::InitializeBase(Context, BI, 0); - InitializationKind Kind = - InitializationKind::CreateDirect(Loc, Loc, Loc); - - // Construct a fake expression to perform the copy overloading. - QualType ArgType = BaseType.getUnqualifiedType(); - if (ConstArg) - ArgType.addConst(); - Expr *Arg = new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue); - - InitializationSequence InitSeq(*this, BaseEntity, Kind, &Arg, 1); - - if (InitSeq.Failed()) + CXXConstructorDecl *BaseCtor = LookupCopyConstructor(BaseDecl, ArgQuals); + if (!BaseCtor || BaseCtor->isDeleted()) + return true; + if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) != + AR_accessible) return true; } @@ -3559,20 +3551,11 @@ bool Sema::ShouldDeleteCopyConstructor(CXXConstructorDecl *CD) { // resolution, as applied to B's [copy] constructor, results in an // ambiguity or a function that is deleted or inaccessible from the // defaulted constructor - InitializedEntity BaseEntity = - InitializedEntity::InitializeBase(Context, BI, BI); - InitializationKind Kind = - InitializationKind::CreateDirect(Loc, Loc, Loc); - - // Construct a fake expression to perform the copy overloading. - QualType ArgType = BaseType.getUnqualifiedType(); - if (ConstArg) - ArgType.addConst(); - Expr *Arg = new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue); - - InitializationSequence InitSeq(*this, BaseEntity, Kind, &Arg, 1); - - if (InitSeq.Failed()) + CXXConstructorDecl *BaseCtor = LookupCopyConstructor(BaseDecl, ArgQuals); + if (!BaseCtor || BaseCtor->isDeleted()) + return true; + if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) != + AR_accessible) return true; } @@ -3625,32 +3608,19 @@ bool Sema::ShouldDeleteCopyConstructor(CXXConstructorDecl *CD) { AR_accessible) return true; } - } - llvm::SmallVector Entities; - QualType CurType = FI->getType(); - Entities.push_back(InitializedEntity::InitializeMember(*FI, 0)); - while (CurType->isArrayType()) { - Entities.push_back(InitializedEntity::InitializeElement(Context, 0, - Entities.back())); - CurType = Context.getAsArrayType(CurType)->getElementType(); + // -- a [non-static data member of class type (or array thereof)] B that + // cannot be [copied] because overload resolution, as applied to B's + // [copy] constructor, results in an ambiguity or a function that is + // deleted or inaccessible from the defaulted constructor + CXXConstructorDecl *FieldCtor = LookupCopyConstructor(FieldRecord, + ArgQuals); + if (!FieldCtor || FieldCtor->isDeleted()) + return true; + if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(), + PDiag()) != AR_accessible) + return true; } - - InitializationKind Kind = - InitializationKind::CreateDirect(Loc, Loc, Loc); - - // Construct a fake expression to perform the copy overloading. - QualType ArgType = FieldType; - if (ArgType->isReferenceType()) - ArgType = ArgType->getPointeeType(); - else if (ConstArg) - ArgType.addConst(); - Expr *Arg = new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue); - - InitializationSequence InitSeq(*this, Entities.back(), Kind, &Arg, 1); - - if (InitSeq.Failed()) - return true; } return false; @@ -7043,6 +7013,7 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { // X::X(const X&) // // if + // FIXME: It ought to be possible to store this on the record. bool HasConstCopyConstructor = true; // -- each direct or virtual base class B of X has a copy @@ -7058,10 +7029,8 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { CXXRecordDecl *BaseClassDecl = cast(Base->getType()->getAs()->getDecl()); - if (!BaseClassDecl->hasDeclaredCopyConstructor()) - DeclareImplicitCopyConstructor(BaseClassDecl); - - HasConstCopyConstructor = BaseClassDecl->hasConstCopyConstructor(); + LookupCopyConstructor(BaseClassDecl, Qualifiers::Const, + &HasConstCopyConstructor); } for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), @@ -7070,10 +7039,8 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { ++Base) { CXXRecordDecl *BaseClassDecl = cast(Base->getType()->getAs()->getDecl()); - if (!BaseClassDecl->hasDeclaredCopyConstructor()) - DeclareImplicitCopyConstructor(BaseClassDecl); - - HasConstCopyConstructor= BaseClassDecl->hasConstCopyConstructor(); + LookupCopyConstructor(BaseClassDecl, Qualifiers::Const, + &HasConstCopyConstructor); } // -- for all the nonstatic data members of X that are of a @@ -7085,13 +7052,9 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { HasConstCopyConstructor && Field != FieldEnd; ++Field) { QualType FieldType = Context.getBaseElementType((*Field)->getType()); - if (const RecordType *FieldClassType = FieldType->getAs()) { - CXXRecordDecl *FieldClassDecl - = cast(FieldClassType->getDecl()); - if (!FieldClassDecl->hasDeclaredCopyConstructor()) - DeclareImplicitCopyConstructor(FieldClassDecl); - - HasConstCopyConstructor = FieldClassDecl->hasConstCopyConstructor(); + if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { + LookupCopyConstructor(FieldClassDecl, Qualifiers::Const, + &HasConstCopyConstructor); } } // Otherwise, the implicitly declared copy constructor will have @@ -7114,11 +7077,8 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { CXXRecordDecl *BaseClassDecl = cast(Base->getType()->getAs()->getDecl()); - if (!BaseClassDecl->hasDeclaredCopyConstructor()) - DeclareImplicitCopyConstructor(BaseClassDecl); - - if (CXXConstructorDecl *CopyConstructor - = BaseClassDecl->getCopyConstructor(Quals)) + if (CXXConstructorDecl *CopyConstructor = + LookupCopyConstructor(BaseClassDecl, Quals)) ExceptSpec.CalledDecl(CopyConstructor); } for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), @@ -7127,11 +7087,8 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { ++Base) { CXXRecordDecl *BaseClassDecl = cast(Base->getType()->getAs()->getDecl()); - if (!BaseClassDecl->hasDeclaredCopyConstructor()) - DeclareImplicitCopyConstructor(BaseClassDecl); - - if (CXXConstructorDecl *CopyConstructor - = BaseClassDecl->getCopyConstructor(Quals)) + if (CXXConstructorDecl *CopyConstructor = + LookupCopyConstructor(BaseClassDecl, Quals)) ExceptSpec.CalledDecl(CopyConstructor); } for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), @@ -7139,15 +7096,10 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { Field != FieldEnd; ++Field) { QualType FieldType = Context.getBaseElementType((*Field)->getType()); - if (const RecordType *FieldClassType = FieldType->getAs()) { - CXXRecordDecl *FieldClassDecl - = cast(FieldClassType->getDecl()); - if (!FieldClassDecl->hasDeclaredCopyConstructor()) - DeclareImplicitCopyConstructor(FieldClassDecl); - - if (CXXConstructorDecl *CopyConstructor - = FieldClassDecl->getCopyConstructor(Quals)) - ExceptSpec.CalledDecl(CopyConstructor); + if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { + if (CXXConstructorDecl *CopyConstructor = + LookupCopyConstructor(FieldClassDecl, Quals)) + ExceptSpec.CalledDecl(CopyConstructor); } } diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index b730408b91..92ade1efcf 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2303,13 +2303,29 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *D, /// \brief Look up the default constructor for the given class. CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) { - SpecialMemberOverloadResult *Result = + SpecialMemberOverloadResult *Result = LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false, false, false); return cast_or_null(Result->getMethod()); } +/// \brief Look up the copy constructor for the given class. +CXXConstructorDecl *Sema::LookupCopyConstructor(CXXRecordDecl *Class, + unsigned Quals, + bool *ConstParamMatch) { + assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && + "non-const, non-volatile qualifiers for copy ctor arg"); + SpecialMemberOverloadResult *Result = + LookupSpecialMember(Class, CXXCopyConstructor, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, false, false, false); + + if (ConstParamMatch) + *ConstParamMatch = Result->hasConstParamMatch(); + + return cast_or_null(Result->getMethod()); +} + /// \brief Look up the constructors for the given class. DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { // If the implicit constructors have not yet been declared, do so now.