зеркало из https://github.com/microsoft/clang-1.git
PR13381: consider cv-qualifiers on a class member's type when determining which
constructor will be used for moving that object, in the computation of its exception specification. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160417 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
500d729e85
Коммит
6a06e5ff3b
|
@ -2124,9 +2124,10 @@ public:
|
|||
unsigned Quals);
|
||||
CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals,
|
||||
bool RValueThis, unsigned ThisQuals);
|
||||
CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class);
|
||||
CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, bool RValueThis,
|
||||
unsigned ThisQuals);
|
||||
CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class,
|
||||
unsigned Quals);
|
||||
CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals,
|
||||
bool RValueThis, unsigned ThisQuals);
|
||||
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
|
||||
|
||||
LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R,
|
||||
|
|
|
@ -7559,7 +7559,9 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
|
|||
QualType FieldType = Context.getBaseElementType(Field->getType());
|
||||
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
|
||||
if (CXXMethodDecl *CopyAssign =
|
||||
LookupCopyingAssignment(FieldClassDecl, ArgQuals, false, 0))
|
||||
LookupCopyingAssignment(FieldClassDecl,
|
||||
ArgQuals | FieldType.getCVRQualifiers(),
|
||||
false, 0))
|
||||
ExceptSpec.CalledDecl(Field->getLocation(), CopyAssign);
|
||||
}
|
||||
}
|
||||
|
@ -7966,7 +7968,7 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
|
|||
CXXRecordDecl *BaseClassDecl
|
||||
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
||||
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
|
||||
false, 0))
|
||||
0, false, 0))
|
||||
ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
|
||||
}
|
||||
|
||||
|
@ -7976,7 +7978,7 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
|
|||
CXXRecordDecl *BaseClassDecl
|
||||
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
||||
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
|
||||
false, 0))
|
||||
0, false, 0))
|
||||
ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
|
||||
}
|
||||
|
||||
|
@ -7986,8 +7988,10 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
|
|||
++Field) {
|
||||
QualType FieldType = Context.getBaseElementType(Field->getType());
|
||||
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
|
||||
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(FieldClassDecl,
|
||||
false, 0))
|
||||
if (CXXMethodDecl *MoveAssign =
|
||||
LookupMovingAssignment(FieldClassDecl,
|
||||
FieldType.getCVRQualifiers(),
|
||||
false, 0))
|
||||
ExceptSpec.CalledDecl(Field->getLocation(), MoveAssign);
|
||||
}
|
||||
}
|
||||
|
@ -8580,7 +8584,8 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
|
|||
QualType FieldType = Context.getBaseElementType(Field->getType());
|
||||
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
|
||||
if (CXXConstructorDecl *CopyConstructor =
|
||||
LookupCopyingConstructor(FieldClassDecl, Quals))
|
||||
LookupCopyingConstructor(FieldClassDecl,
|
||||
Quals | FieldType.getCVRQualifiers()))
|
||||
ExceptSpec.CalledDecl(Field->getLocation(), CopyConstructor);
|
||||
}
|
||||
}
|
||||
|
@ -8708,7 +8713,8 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
|
|||
|
||||
if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
|
||||
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
|
||||
CXXConstructorDecl *Constructor = LookupMovingConstructor(BaseClassDecl);
|
||||
CXXConstructorDecl *Constructor =
|
||||
LookupMovingConstructor(BaseClassDecl, 0);
|
||||
// If this is a deleted function, add it anyway. This might be conformant
|
||||
// with the standard. This might not. I'm not sure. It might not matter.
|
||||
if (Constructor)
|
||||
|
@ -8722,7 +8728,8 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
|
|||
B != BEnd; ++B) {
|
||||
if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
|
||||
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
|
||||
CXXConstructorDecl *Constructor = LookupMovingConstructor(BaseClassDecl);
|
||||
CXXConstructorDecl *Constructor =
|
||||
LookupMovingConstructor(BaseClassDecl, 0);
|
||||
// If this is a deleted function, add it anyway. This might be conformant
|
||||
// with the standard. This might not. I'm not sure. It might not matter.
|
||||
if (Constructor)
|
||||
|
@ -8734,10 +8741,10 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
|
|||
for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
|
||||
FEnd = ClassDecl->field_end();
|
||||
F != FEnd; ++F) {
|
||||
if (const RecordType *RecordTy
|
||||
= Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
|
||||
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
|
||||
CXXConstructorDecl *Constructor = LookupMovingConstructor(FieldRecDecl);
|
||||
QualType FieldType = Context.getBaseElementType(F->getType());
|
||||
if (CXXRecordDecl *FieldRecDecl = FieldType->getAsCXXRecordDecl()) {
|
||||
CXXConstructorDecl *Constructor =
|
||||
LookupMovingConstructor(FieldRecDecl, FieldType.getCVRQualifiers());
|
||||
// If this is a deleted function, add it anyway. This might be conformant
|
||||
// with the standard. This might not. I'm not sure. It might not matter.
|
||||
// In particular, the problem is that this function never gets called. It
|
||||
|
|
|
@ -2432,10 +2432,11 @@ CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class,
|
|||
}
|
||||
|
||||
/// \brief Look up the moving constructor for the given class.
|
||||
CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class) {
|
||||
CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class,
|
||||
unsigned Quals) {
|
||||
SpecialMemberOverloadResult *Result =
|
||||
LookupSpecialMember(Class, CXXMoveConstructor, false,
|
||||
false, false, false, false);
|
||||
LookupSpecialMember(Class, CXXMoveConstructor, Quals & Qualifiers::Const,
|
||||
Quals & Qualifiers::Volatile, false, false, false);
|
||||
|
||||
return cast_or_null<CXXConstructorDecl>(Result->getMethod());
|
||||
}
|
||||
|
@ -2476,12 +2477,14 @@ CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class,
|
|||
|
||||
/// \brief Look up the moving assignment operator for the given class.
|
||||
CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class,
|
||||
unsigned Quals,
|
||||
bool RValueThis,
|
||||
unsigned ThisQuals) {
|
||||
assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&
|
||||
"non-const, non-volatile qualifiers for copy assignment this");
|
||||
SpecialMemberOverloadResult *Result =
|
||||
LookupSpecialMember(Class, CXXMoveAssignment, false, false, RValueThis,
|
||||
LookupSpecialMember(Class, CXXMoveAssignment, Quals & Qualifiers::Const,
|
||||
Quals & Qualifiers::Volatile, RValueThis,
|
||||
ThisQuals & Qualifiers::Const,
|
||||
ThisQuals & Qualifiers::Volatile);
|
||||
|
||||
|
|
|
@ -39,3 +39,27 @@ struct IC1 {
|
|||
// we cannot currently compute the set of thrown types.
|
||||
static_assert(noexcept(IC0()), "IC0() does not throw");
|
||||
static_assert(!noexcept(IC1()), "IC1() throws");
|
||||
|
||||
namespace PR13381 {
|
||||
struct NoThrowMove {
|
||||
NoThrowMove(const NoThrowMove &);
|
||||
NoThrowMove(NoThrowMove &&) noexcept;
|
||||
NoThrowMove &operator=(const NoThrowMove &);
|
||||
NoThrowMove &operator=(NoThrowMove &&) noexcept;
|
||||
};
|
||||
struct NoThrowMoveOnly {
|
||||
NoThrowMoveOnly(NoThrowMoveOnly &&) noexcept;
|
||||
NoThrowMoveOnly &operator=(NoThrowMoveOnly &&) noexcept;
|
||||
};
|
||||
struct X {
|
||||
const NoThrowMove a;
|
||||
NoThrowMoveOnly b;
|
||||
|
||||
static X val();
|
||||
static X &ref();
|
||||
};
|
||||
// These both perform a move, but that copy might throw, because it calls
|
||||
// NoThrowMove's copy constructor (because PR13381::a is const).
|
||||
static_assert(!noexcept(X(X::val())), "");
|
||||
static_assert(!noexcept(X::ref() = X::val()), "");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче