diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -58,6 +58,8 @@ ABI Changes in This Version --------------------------- +- ``__is_trivial`` has changed for a small category of classes with constrained default constructors (`#60697 `_). + *FIXME: Remove this note if we've backported this change to the Clang 16 branch.* What's New in Clang |release|? ============================== diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2501,11 +2501,13 @@ return true; if (const auto *RT = CanonicalType->getAs()) { if (const auto *ClassDecl = dyn_cast(RT->getDecl())) { - // C++11 [class]p6: - // A trivial class is a class that has a default constructor, - // has no non-trivial default constructors, and is trivially - // copyable. - return ClassDecl->hasDefaultConstructor() && + // C++20 [class]p6: + // A trivial class is a class that is trivially copyable, and + // has one or more eligible default constructors such that each is + // trivial. + // FIXME: We should merge this definition of triviality into + // CXXRecordDecl::isTrivial. Currently it computes the wrong thing. + return ClassDecl->hasTrivialDefaultConstructor() && !ClassDecl->hasNonTrivialDefaultConstructor() && ClassDecl->isTriviallyCopyable(); } diff --git a/clang/test/SemaCXX/constrained-special-member-functions.cpp b/clang/test/SemaCXX/constrained-special-member-functions.cpp --- a/clang/test/SemaCXX/constrained-special-member-functions.cpp +++ b/clang/test/SemaCXX/constrained-special-member-functions.cpp @@ -265,3 +265,37 @@ static_assert(__is_trivially_constructible(D), ""); } + +namespace GH60697 { + +template +struct X { + X() requires false = default; +}; +static_assert(!__is_trivial(X)); + +template +struct S { + S() requires(__is_trivially_constructible(T)) = default; + + S() requires(!__is_trivially_constructible(T) && + __is_constructible(T)) {} + + T t; +}; + +struct D { + D(int i) : i(i) {} + int i; +}; +static_assert(!__is_trivially_constructible(D)); +static_assert(!__is_constructible(D)); +static_assert(!__is_trivial(D)); + +static_assert(!__is_trivially_constructible(S)); +static_assert(!__is_constructible(S)); + +static_assert(__is_trivial(S)); +static_assert(!__is_trivial(S)); + +}