aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hunt <scshunt@csclub.uwaterloo.ca>2011-06-10 04:44:37 +0000
committerSean Hunt <scshunt@csclub.uwaterloo.ca>2011-06-10 04:44:37 +0000
commitc530d1758cef1acc596f2ec905665da534e66d29 (patch)
treef8e6f3c95cdf3364d393808a9bc0e85062007cea
parentb320e0c322fb71d6235ebca9ec22940a97bdcdc7 (diff)
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
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaDeclCXX.cpp130
-rw-r--r--lib/Sema/SemaLookup.cpp18
3 files changed, 61 insertions, 90 deletions
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<InitializedEntity, 4> 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<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->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<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->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<RecordType>()) {
- CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(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<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->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<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->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<RecordType>()) {
- CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(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<CXXConstructorDecl>(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<CXXConstructorDecl>(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.