diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-const.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-const.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-const.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-const.cpp @@ -10,12 +10,12 @@ }; // This class is non-trivially copyable because the copy-constructor and copy -// assignment take non-const references. +// assignment take non-const references and are user-provided. struct ModifiesRightSide { ModifiesRightSide() = default; - ModifiesRightSide(ModifiesRightSide &) = default; + ModifiesRightSide(ModifiesRightSide &); bool operator<(ModifiesRightSide &) const; - ModifiesRightSide &operator=(ModifiesRightSide &) = default; + ModifiesRightSide &operator=(ModifiesRightSide &); }; template diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9772,11 +9772,9 @@ case CXXCopyConstructor: case CXXCopyAssignment: { - // Trivial copy operations always have const, non-volatile parameter types. - ConstArg = true; const ParmVarDecl *Param0 = MD->getParamDecl(0); const ReferenceType *RT = Param0->getType()->getAs(); - if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) { + if (!RT) { if (Diagnose) Diag(Param0->getLocation(), diag::note_nontrivial_param_type) << Param0->getSourceRange() << Param0->getType() @@ -9784,6 +9782,11 @@ Context.getRecordType(RD).withConst()); return false; } + + if (RT && ((RT->getPointeeType().getCVRQualifiers() & Qualifiers::Const) == + Qualifiers::Const)) { + ConstArg = true; + } break; } diff --git a/clang/test/CXX/special/class.copy/p12-0x.cpp b/clang/test/CXX/special/class.copy/p12-0x.cpp --- a/clang/test/CXX/special/class.copy/p12-0x.cpp +++ b/clang/test/CXX/special/class.copy/p12-0x.cpp @@ -28,7 +28,18 @@ struct NonConstCopy { NonConstCopy(NonConstCopy &) = default; }; -using _ = not_trivially_copyable; +static_assert(__has_trivial_copy(NonConstCopy), ""); +static_assert(__is_trivially_constructible(NonConstCopy, NonConstCopy &), ""); +static_assert(!__is_trivially_constructible(NonConstCopy, NonConstCopy), ""); +static_assert(!__is_trivially_constructible(NonConstCopy, const NonConstCopy &), ""); +static_assert(!__is_trivially_constructible(NonConstCopy, NonConstCopy &&), ""); + +struct DefaultedSpecialMembers { + DefaultedSpecialMembers(const DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers(DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers(DefaultedSpecialMembers &&) = default; +}; +using _ = trivially_copyable; // class X has no virtual functions struct VFn { diff --git a/clang/test/CXX/special/class.copy/p25-0x.cpp b/clang/test/CXX/special/class.copy/p25-0x.cpp --- a/clang/test/CXX/special/class.copy/p25-0x.cpp +++ b/clang/test/CXX/special/class.copy/p25-0x.cpp @@ -31,7 +31,22 @@ struct NonConstCopy { NonConstCopy &operator=(NonConstCopy &) = default; }; -using _ = not_trivially_assignable; +static_assert(__has_trivial_assign(NonConstCopy), ""); +static_assert(__is_trivially_assignable(NonConstCopy &, NonConstCopy &), ""); +static_assert(!__is_trivially_assignable(NonConstCopy &, const NonConstCopy &), ""); +static_assert(!__is_trivially_assignable(NonConstCopy &, NonConstCopy), ""); +static_assert(!__is_trivially_assignable(NonConstCopy &, NonConstCopy &&), ""); +static_assert(__is_trivially_assignable(NonConstCopy &&, NonConstCopy &), ""); +static_assert(!__is_trivially_assignable(NonConstCopy &&, const NonConstCopy &), ""); +static_assert(!__is_trivially_assignable(NonConstCopy &&, NonConstCopy), ""); +static_assert(!__is_trivially_assignable(NonConstCopy &&, NonConstCopy &&), ""); + +struct DefaultedSpecialMembers { + DefaultedSpecialMembers &operator=(const DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(DefaultedSpecialMembers &&) = default; +}; +using _ = trivially_assignable; // class X has no virtual functions struct VFn {