blob: 8ac17e7838ef871cf734befd4a7245beebad29fd [file] [log] [blame]
// RUN: %clang_cc1 -verify -std=c++20 %s
template <int N>
concept C0 = (N == 0);
template <int N>
concept C1 = (N == 1);
template <int N>
concept C2 = (N == 2);
// Checks are indexed by:
// Definition:
// 1. Explicitly defaulted definition
// 2. Deleted definition
// 3. User provided definition
// We have a less constrained user provided method that should not disable
// the (copyable) triviality of the type.
// Note that because Clang does not implement DRs 1496 and 1734, we say some
// classes are trivial when the SMFs are deleted.
template <int N>
struct DefaultConstructorChecker {
DefaultConstructorChecker() requires C0<N> = default;
DefaultConstructorChecker() requires C1<N> = delete;
DefaultConstructorChecker() requires C2<N>;
DefaultConstructorChecker();
};
static_assert(__is_trivially_copyable(DefaultConstructorChecker<0>));
static_assert(__is_trivially_copyable(DefaultConstructorChecker<1>));
static_assert(__is_trivially_copyable(DefaultConstructorChecker<2>));
static_assert(__is_trivially_copyable(DefaultConstructorChecker<3>));
static_assert(__is_trivial(DefaultConstructorChecker<0>));
// FIXME: DR1496
static_assert(__is_trivial(DefaultConstructorChecker<1>));
static_assert(!__is_trivial(DefaultConstructorChecker<2>));
static_assert(!__is_trivial(DefaultConstructorChecker<3>));
template <int N>
struct CopyConstructorChecker {
CopyConstructorChecker(const CopyConstructorChecker&) requires C0<N> = default;
CopyConstructorChecker(const CopyConstructorChecker&) requires C1<N> = delete;
CopyConstructorChecker(const CopyConstructorChecker&) requires C2<N>;
CopyConstructorChecker(const CopyConstructorChecker&);
};
static_assert(__is_trivially_copyable(CopyConstructorChecker<0>));
// FIXME: DR1734
static_assert(__is_trivially_copyable(CopyConstructorChecker<1>));
static_assert(!__is_trivially_copyable(CopyConstructorChecker<2>));
static_assert(!__is_trivially_copyable(CopyConstructorChecker<3>));
static_assert(!__is_trivial(CopyConstructorChecker<0>));
static_assert(!__is_trivial(CopyConstructorChecker<1>));
static_assert(!__is_trivial(CopyConstructorChecker<2>));
static_assert(!__is_trivial(CopyConstructorChecker<3>));
template <int N>
struct MoveConstructorChecker {
MoveConstructorChecker(MoveConstructorChecker&&) requires C0<N> = default;
MoveConstructorChecker(MoveConstructorChecker&&) requires C1<N> = delete;
MoveConstructorChecker(MoveConstructorChecker&&) requires C2<N>;
MoveConstructorChecker(MoveConstructorChecker&&);
};
static_assert(__is_trivially_copyable(MoveConstructorChecker<0>));
// FIXME: DR1734
static_assert(__is_trivially_copyable(MoveConstructorChecker<1>));
static_assert(!__is_trivially_copyable(MoveConstructorChecker<2>));
static_assert(!__is_trivially_copyable(MoveConstructorChecker<3>));
static_assert(!__is_trivial(MoveConstructorChecker<0>));
static_assert(!__is_trivial(MoveConstructorChecker<1>));
static_assert(!__is_trivial(MoveConstructorChecker<2>));
static_assert(!__is_trivial(MoveConstructorChecker<3>));
template <int N>
struct MoveAssignmentChecker {
MoveAssignmentChecker& operator=(MoveAssignmentChecker&&) requires C0<N> = default;
MoveAssignmentChecker& operator=(MoveAssignmentChecker&&) requires C1<N> = delete;
MoveAssignmentChecker& operator=(MoveAssignmentChecker&&) requires C2<N>;
MoveAssignmentChecker& operator=(MoveAssignmentChecker&&);
};
static_assert(__is_trivially_copyable(MoveAssignmentChecker<0>));
// FIXME: DR1734.
static_assert(__is_trivially_copyable(MoveAssignmentChecker<1>));
static_assert(!__is_trivially_copyable(MoveAssignmentChecker<2>));
static_assert(!__is_trivially_copyable(MoveAssignmentChecker<3>));
static_assert(__is_trivial(MoveAssignmentChecker<0>));
// FIXME: DR1734.
static_assert(__is_trivial(MoveAssignmentChecker<1>));
static_assert(!__is_trivial(MoveAssignmentChecker<2>));
static_assert(!__is_trivial(MoveAssignmentChecker<3>));
template <int N>
struct CopyAssignmentChecker {
CopyAssignmentChecker& operator=(const CopyAssignmentChecker&) requires C0<N> = default;
CopyAssignmentChecker& operator=(const CopyAssignmentChecker&) requires C1<N> = delete;
CopyAssignmentChecker& operator=(const CopyAssignmentChecker&) requires C2<N>;
CopyAssignmentChecker& operator=(const CopyAssignmentChecker&);
};
static_assert(__is_trivially_copyable(CopyAssignmentChecker<0>));
// FIXME: DR1734.
static_assert(__is_trivially_copyable(CopyAssignmentChecker<1>));
static_assert(!__is_trivially_copyable(CopyAssignmentChecker<2>));
static_assert(!__is_trivially_copyable(CopyAssignmentChecker<3>));
static_assert(__is_trivial(CopyAssignmentChecker<0>));
// FIXME: DR1734.
static_assert(__is_trivial(CopyAssignmentChecker<1>));
static_assert(!__is_trivial(CopyAssignmentChecker<2>));
static_assert(!__is_trivial(CopyAssignmentChecker<3>));
template <int N>
struct KindComparisonChecker1 {
KindComparisonChecker1& operator=(const KindComparisonChecker1&) requires C0<N> = default;
KindComparisonChecker1& operator=(KindComparisonChecker1&);
};
template <int N>
struct KindComparisonChecker2 {
KindComparisonChecker2& operator=(const KindComparisonChecker2&) requires C0<N> = default;
const KindComparisonChecker2& operator=(KindComparisonChecker2&) const;
};
template <int N>
struct KindComparisonChecker3 {
using Alias = KindComparisonChecker3;
Alias& operator=(const Alias&) requires C0<N> = default;
KindComparisonChecker3& operator=(const KindComparisonChecker3&);
};
static_assert(!__is_trivial(KindComparisonChecker1<0>));
static_assert(!__is_trivially_copyable(KindComparisonChecker1<0>));
static_assert(!__is_trivial(KindComparisonChecker2<0>));
static_assert(!__is_trivially_copyable(KindComparisonChecker2<0>));
static_assert(__is_trivial(KindComparisonChecker3<0>));
static_assert(__is_trivially_copyable(KindComparisonChecker3<0>));
template <class T>
concept HasA = requires(T t) {
{ t.a() };
};
template <class T>
concept HasAB = HasA<T> && requires(T t) {
{ t.b() };
};
template <class T>
concept HasAC = HasA<T> && requires(T t) {
{ t.c() };
};
template <class T>
concept HasABC = HasAB<T> && HasAC<T> && requires(T t) {
{ t.c() };
};
template <class T>
struct ComplexConstraints {
ComplexConstraints() requires HasABC<T> = default;
ComplexConstraints() requires HasAB<T>;
ComplexConstraints() requires HasAC<T>;
ComplexConstraints() requires HasA<T> = delete;
ComplexConstraints();
};
struct A {
void a();
};
struct AB {
void a();
void b();
};
struct ABC {
void a();
void b();
void c();
};
struct AC {
void a();
void c();
};
static_assert(__is_trivial(ComplexConstraints<ABC>), "");
static_assert(!__is_trivial(ComplexConstraints<AB>), "");
static_assert(!__is_trivial(ComplexConstraints<AC>), "");
static_assert(__is_trivial(ComplexConstraints<A>), "");
static_assert(!__is_trivial(ComplexConstraints<int>), "");
// This is evaluated at the completion of CRTPBase, while `T` is not yet completed.
// This is probably correct behavior.
template <class T>
struct CRTPBase {
CRTPBase() requires (sizeof(T) > 0);
CRTPBase() = default;
};
struct Child : CRTPBase<Child> { int x; };
static Child c;
namespace GH57046 {
template<unsigned N>
struct Foo {
Foo() requires (N==1) {} // expected-note {{declared here}}
Foo() requires (N==2) = default;
};
template <unsigned N, unsigned M>
struct S {
Foo<M> data;
S() requires (N==1) {}
consteval S() requires (N==2) = default; // expected-note {{non-constexpr constructor 'Foo' cannot be used in a constant expression}}
};
void func() {
S<2, 1> s1; // expected-error {{is not a constant expression}} expected-note {{in call to 'S()'}}
S<2, 2> s2;
}
}
namespace GH59206 {
struct A {
A() = default; //eligible, second constructor unsatisfied
template<class... Args>
A(Args&&... args) requires (sizeof...(Args) > 0) {}
};
struct B {
B() = default; //ineligible, second constructor more constrained
template<class... Args>
B(Args&&... args) requires (sizeof...(Args) == 0) {}
};
struct C {
C() = default; //eligible, but
template<class... Args> //also eligible and non-trivial
C(Args&&... args) {}
};
struct D : B {};
static_assert(__is_trivially_copyable(A), "");
static_assert(__is_trivially_copyable(B), "");
static_assert(__is_trivially_copyable(C), "");
static_assert(__is_trivially_copyable(D), "");
// FIXME: Update when https://github.com/llvm/llvm-project/issues/59206 is
// resolved.
static_assert(!__is_trivial(A), "");
static_assert(!__is_trivial(B), "");
static_assert(!__is_trivial(C), "");
static_assert(__is_trivial(D), "");
static_assert(__is_trivially_constructible(A), "");
static_assert(__is_trivially_constructible(B), "");
static_assert(__is_trivially_constructible(C), "");
static_assert(__is_trivially_constructible(D), "");
}
namespace GH60697 {
template <class T>
struct X {
X() requires false = default;
};
static_assert(!__is_trivial(X<int>));
template <class T>
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<D>));
static_assert(!__is_constructible(S<D>));
static_assert(__is_trivial(S<int>));
static_assert(!__is_trivial(S<D>));
}
namespace GH62555 {
template <bool B>
struct ExplicitTemplateArgs {
ExplicitTemplateArgs(ExplicitTemplateArgs&&) = default;
ExplicitTemplateArgs(ExplicitTemplateArgs<false>&&) requires B {};
};
static_assert(__is_trivially_copyable(ExplicitTemplateArgs<false>));
static_assert(__is_trivially_copyable(ExplicitTemplateArgs<true>));
}