// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// test <type_traits> header, part 3
#define TEST_NAME "<type_traits>, part 3"

#include "tdefs.h"
#include "typetr.h"
#include <type_traits>

// TESTS
static void t_is_trivially_constructible() { // test is_trivially_constructible<T, Args...> for various types
    T_UNSPEC_CV(is_trivially_constructible, void, false);
    T_UNSPEC_CV(is_trivially_constructible, char, true);
    T_UNSPEC_CV(is_trivially_constructible, signed char, true);
    T_UNSPEC_CV(is_trivially_constructible, unsigned char, true);
    T_UNSPEC_CV(is_trivially_constructible, wchar_t, true);
    T_UNSPEC_CV(is_trivially_constructible, short, true);
    T_UNSPEC_CV(is_trivially_constructible, unsigned short, true);
    T_UNSPEC_CV(is_trivially_constructible, int, true);
    T_UNSPEC_CV(is_trivially_constructible, unsigned int, true);
    T_UNSPEC_CV(is_trivially_constructible, long, true);
    T_UNSPEC_CV(is_trivially_constructible, unsigned long, true);

    T_UNSPEC_CV(is_trivially_constructible, long long, true);
    T_UNSPEC_CV(is_trivially_constructible, unsigned long long, true);

    T_UNSPEC_CV(is_trivially_constructible, float, true);
    T_UNSPEC_CV(is_trivially_constructible, double, true);
    T_UNSPEC_CV(is_trivially_constructible, long double, true);
    T_UNSPEC_CV(is_trivially_constructible, int*, true);
    T_UNSPEC(is_trivially_constructible, int&, false);
    T_UNSPEC_CV(is_trivially_constructible, B, false);
    T_UNSPEC_CV(is_trivially_constructible, C, false);
    T_UNSPEC_CV(is_trivially_constructible, D, true);
    T_UNSPEC_CV(is_trivially_constructible, pmo, true);
    T_UNSPEC_CV(is_trivially_constructible, pmoc, true);
    T_UNSPEC_CV(is_trivially_constructible, pmov, true);
    T_UNSPEC_CV(is_trivially_constructible, pmocv, true);
    T_UNSPEC_CV(is_trivially_constructible, pmf, true);
    T_UNSPEC_CV(is_trivially_constructible, pmfc, true);
    T_UNSPEC_CV(is_trivially_constructible, pmfv, true);
    T_UNSPEC_CV(is_trivially_constructible, pmfcv, true);
    T_UNSPEC_CV(is_trivially_constructible, arr_t, true);
    T_UNSPEC_CV(is_trivially_constructible, enum_t, true);
    T_UNSPEC_CV(is_trivially_constructible, pf, true);
    T_UNSPEC(is_trivially_constructible, func, false);
    T_UNSPEC_CV(is_trivially_constructible, void*, true);

    bool ans = STD is_trivially_constructible<int>::value;
    CHECK(ans);
    ans = STD is_trivially_constructible<int, int>::value;
    CHECK(ans);
    ans = STD is_trivially_constructible<int, int, int>::value;
    CHECK(!ans);
    ans = STD is_trivially_constructible<int, int, int, int>::value;
    CHECK(!ans);
    ans = STD is_trivially_constructible<int, int, int, int, int>::value;
    CHECK(!ans);
}

static void t_is_trivially_default_constructible() { // test is_trivially_default_constructible<T> for various types
                                                     // (minimal tests in absence of compiler support)
    T_TRIVIAL_CV(is_trivially_default_constructible, void, false);
    T_TRIVIAL_CV(is_trivially_default_constructible, char, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, signed char, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, unsigned char, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, wchar_t, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, short, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, unsigned short, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, int, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, unsigned int, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, long, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, unsigned long, true);

    T_TRIVIAL_CV(is_trivially_default_constructible, long long, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, unsigned long long, true);

    T_TRIVIAL_CV(is_trivially_default_constructible, float, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, double, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, long double, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, int*, true);
    T_TRIVIAL(is_trivially_default_constructible, int&, false);
    T_TRIVIAL_CV(is_trivially_default_constructible, B, false);
    T_TRIVIAL_CV(is_trivially_default_constructible, C, false);
    T_TRIVIAL_CV(is_trivially_default_constructible, D, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, pmo, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, pmoc, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, pmov, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, pmocv, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, pmf, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, pmfc, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, pmfv, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, pmfcv, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, arr_t, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, enum_t, true);
    T_TRIVIAL_CV(is_trivially_default_constructible, pf, true);
    T_TRIVIAL(is_trivially_default_constructible, func, false);
    T_TRIVIAL_CV(is_trivially_default_constructible, void*, true);
}

static void t_is_trivially_copy_constructible() { // test is_trivially_copy_constructible<T> for various types
    T_UNSPEC_CV(is_trivially_copy_constructible, void, false);
    T_UNSPEC_CV(is_trivially_copy_constructible, char, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, signed char, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, unsigned char, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, wchar_t, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, short, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, unsigned short, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, int, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, unsigned int, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, long, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, unsigned long, true);

    T_UNSPEC_CV(is_trivially_copy_constructible, long long, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, unsigned long long, true);

    T_UNSPEC_CV(is_trivially_copy_constructible, float, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, double, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, long double, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, int*, true);
    T_UNSPEC(is_trivially_copy_constructible, int&, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, B, false);
    T_UNSPEC_CV(is_trivially_copy_constructible, C, false);
    T_UNSPEC_C(is_trivially_copy_constructible, D, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, pmo, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, pmoc, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, pmov, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, pmocv, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, pmf, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, pmfc, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, pmfv, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, pmfcv, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, arr_t, false);
    T_UNSPEC_CV(is_trivially_copy_constructible, enum_t, true);
    T_UNSPEC_CV(is_trivially_copy_constructible, pf, true);
    T_UNSPEC(is_trivially_copy_constructible, func, false);
    T_UNSPEC_CV(is_trivially_copy_constructible, void*, true);
}

static void t_is_trivially_copyable() { // test is_trivially_copyable<T> for various types
    T_UNSPEC_CV(is_trivially_copyable, void, false);
    T_UNSPEC_C(is_trivially_copyable, char, true);
    T_UNSPEC_C(is_trivially_copyable, signed char, true);
    T_UNSPEC_C(is_trivially_copyable, unsigned char, true);
    T_UNSPEC_C(is_trivially_copyable, wchar_t, true);
    T_UNSPEC_C(is_trivially_copyable, short, true);
    T_UNSPEC_C(is_trivially_copyable, unsigned short, true);
    T_UNSPEC_C(is_trivially_copyable, int, true);
    T_UNSPEC_C(is_trivially_copyable, unsigned int, true);
    T_UNSPEC_C(is_trivially_copyable, long, true);
    T_UNSPEC_C(is_trivially_copyable, unsigned long, true);

    T_UNSPEC_C(is_trivially_copyable, long long, true);
    T_UNSPEC_C(is_trivially_copyable, unsigned long long, true);

    T_UNSPEC_C(is_trivially_copyable, float, true);
    T_UNSPEC_C(is_trivially_copyable, double, true);
    T_UNSPEC_C(is_trivially_copyable, long double, true);
    T_UNSPEC_C(is_trivially_copyable, int*, true);
    T_UNSPEC(is_trivially_copyable, int&, false);
    T_UNSPEC_CV(is_trivially_copyable, B, false);
    T_UNSPEC_CV(is_trivially_copyable, C, false);
    T_UNSPEC_C(is_trivially_copyable, D, true);
    T_UNSPEC_C(is_trivially_copyable, pmo, true);
    T_UNSPEC_C(is_trivially_copyable, pmoc, true);
    T_UNSPEC_C(is_trivially_copyable, pmov, true);
    T_UNSPEC_C(is_trivially_copyable, pmocv, true);
    T_UNSPEC_C(is_trivially_copyable, pmf, true);
    T_UNSPEC_C(is_trivially_copyable, pmfc, true);
    T_UNSPEC_C(is_trivially_copyable, pmfv, true);
    T_UNSPEC_C(is_trivially_copyable, pmfcv, true);
    T_UNSPEC_C(is_trivially_copyable, arr_t, true);
    T_UNSPEC_C(is_trivially_copyable, enum_t, true);
    T_UNSPEC_C(is_trivially_copyable, pf, true);
    T_UNSPEC(is_trivially_copyable, func, false);
    T_UNSPEC_C(is_trivially_copyable, void*, true);
}

static void t_is_trivially_move_constructible() { // test is_trivially_move_constructible<T> for various types
                                                  // (minimal tests in absence of compiler support)
    T_TRIVIAL_CV(is_trivially_move_constructible, void, false);
    T_TRIVIAL_CV(is_trivially_move_constructible, char, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, signed char, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, unsigned char, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, wchar_t, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, short, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, unsigned short, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, int, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, unsigned int, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, long, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, unsigned long, true);

    T_TRIVIAL_CV(is_trivially_move_constructible, long long, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, unsigned long long, true);

    T_TRIVIAL_CV(is_trivially_move_constructible, float, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, double, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, long double, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, int*, true);
    T_TRIVIAL(is_trivially_move_constructible, int&, true);

    T_TRIVIAL_CV(is_trivially_move_constructible, B, false);
    T_TRIVIAL_CV(is_trivially_move_constructible, C, false);

    T_TRIVIAL_C(is_trivially_move_constructible, D, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, pmo, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, pmoc, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, pmov, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, pmocv, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, pmf, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, pmfc, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, pmfv, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, pmfcv, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, arr_t, false);
    T_TRIVIAL_CV(is_trivially_move_constructible, enum_t, true);
    T_TRIVIAL_CV(is_trivially_move_constructible, pf, true);
    T_TRIVIAL(is_trivially_move_constructible, func, false);
    T_TRIVIAL_CV(is_trivially_move_constructible, void*, true);
}

static void t_is_trivially_assignable() { // test is_trivially_assignable<T> for various types
                                          // (minimal tests in absence of compiler support)
    bool ans = STD is_trivially_assignable<B, B>::value;
    CHECK(!ans);
    ans = STD is_trivially_assignable<int&, int>::value;
    CHECK(ans);
    ans = STD is_trivially_assignable<int&, B>::value;
    CHECK(!ans);
    // ans = STD is_trivially_assignable<void, void>::value;
    CHECK(!ans);
}

static void t_is_trivially_copy_assignable() { // test is_trivially_copy_assignable<T> for various types
                                               // (minimal tests in absence of compiler support)
    T_TRIVIAL_V(is_trivially_copy_assignable, void, false);
    T_TRIVIAL_V(is_trivially_copy_assignable, char, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, signed char, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, unsigned char, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, wchar_t, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, short, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, unsigned short, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, int, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, unsigned int, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, long, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, unsigned long, true);

    T_TRIVIAL_V(is_trivially_copy_assignable, long long, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, unsigned long long, true);

    T_TRIVIAL_V(is_trivially_copy_assignable, float, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, double, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, long double, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, int*, true);
    T_TRIVIAL(is_trivially_copy_assignable, int&, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, B, false);
    T_TRIVIAL_V(is_trivially_copy_assignable, C, false);
    T_TRIVIAL(is_trivially_copy_assignable, D, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, pmo, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, pmoc, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, pmov, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, pmocv, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, pmf, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, pmfc, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, pmfv, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, pmfcv, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, arr_t, false);
    T_TRIVIAL_V(is_trivially_copy_assignable, enum_t, true);
    T_TRIVIAL_V(is_trivially_copy_assignable, pf, true);
    T_TRIVIAL(is_trivially_copy_assignable, func, false);
    T_TRIVIAL_V(is_trivially_copy_assignable, void*, true);
}

static void t_is_trivially_move_assignable() { // test is_trivially_move_assignable<T> for various types
                                               // (minimal tests in absence of compiler support)
    // T_TRIVIAL_V(is_trivially_move_assignable, void, false);
    T_TRIVIAL_V(is_trivially_move_assignable, char, true);
    T_TRIVIAL_V(is_trivially_move_assignable, signed char, true);
    T_TRIVIAL_V(is_trivially_move_assignable, unsigned char, true);
    T_TRIVIAL_V(is_trivially_move_assignable, wchar_t, true);
    T_TRIVIAL_V(is_trivially_move_assignable, short, true);
    T_TRIVIAL_V(is_trivially_move_assignable, unsigned short, true);
    T_TRIVIAL_V(is_trivially_move_assignable, int, true);
    T_TRIVIAL_V(is_trivially_move_assignable, unsigned int, true);
    T_TRIVIAL_V(is_trivially_move_assignable, long, true);
    T_TRIVIAL_V(is_trivially_move_assignable, unsigned long, true);

    T_TRIVIAL_V(is_trivially_move_assignable, long long, true);
    T_TRIVIAL_V(is_trivially_move_assignable, unsigned long long, true);

    T_TRIVIAL_V(is_trivially_move_assignable, float, true);
    T_TRIVIAL_V(is_trivially_move_assignable, double, true);
    T_TRIVIAL_V(is_trivially_move_assignable, long double, true);
    T_TRIVIAL_V(is_trivially_move_assignable, int*, true);
    T_TRIVIAL(is_trivially_move_assignable, int&, true);

    T_TRIVIAL_V(is_trivially_move_assignable, B, false);
    T_TRIVIAL_V(is_trivially_move_assignable, C, false);

    T_TRIVIAL(is_trivially_move_assignable, D, true);
    T_TRIVIAL_V(is_trivially_move_assignable, pmo, true);
    T_TRIVIAL_V(is_trivially_move_assignable, pmoc, true);
    T_TRIVIAL_V(is_trivially_move_assignable, pmov, true);
    T_TRIVIAL_V(is_trivially_move_assignable, pmocv, true);
    T_TRIVIAL_V(is_trivially_move_assignable, pmf, true);
    T_TRIVIAL_V(is_trivially_move_assignable, pmfc, true);
    T_TRIVIAL_V(is_trivially_move_assignable, pmfv, true);
    T_TRIVIAL_V(is_trivially_move_assignable, pmfcv, true);
    T_TRIVIAL_V(is_trivially_move_assignable, arr_t, false);
    T_TRIVIAL_V(is_trivially_move_assignable, enum_t, true);
    T_TRIVIAL_V(is_trivially_move_assignable, pf, true);
    T_TRIVIAL(is_trivially_move_assignable, func, false);
    T_TRIVIAL_V(is_trivially_move_assignable, void*, true);
}

static void t_is_trivially_destructible() { // test is_trivially_destructible<T> for various types
                                            // (minimal tests in absence of compiler support)
    T_TRIVIAL_CV(is_trivially_destructible, void, false);
    T_TRIVIAL_CV(is_trivially_destructible, char, true);
    T_TRIVIAL_CV(is_trivially_destructible, signed char, true);
    T_TRIVIAL_CV(is_trivially_destructible, unsigned char, true);
    T_TRIVIAL_CV(is_trivially_destructible, wchar_t, true);
    T_TRIVIAL_CV(is_trivially_destructible, short, true);
    T_TRIVIAL_CV(is_trivially_destructible, unsigned short, true);
    T_TRIVIAL_CV(is_trivially_destructible, int, true);
    T_TRIVIAL_CV(is_trivially_destructible, unsigned int, true);
    T_TRIVIAL_CV(is_trivially_destructible, long, true);
    T_TRIVIAL_CV(is_trivially_destructible, unsigned long, true);

    T_TRIVIAL_CV(is_trivially_destructible, long long, true);
    T_TRIVIAL_CV(is_trivially_destructible, unsigned long long, true);

    T_TRIVIAL_CV(is_trivially_destructible, float, true);
    T_TRIVIAL_CV(is_trivially_destructible, double, true);
    T_TRIVIAL_CV(is_trivially_destructible, long double, true);
    T_TRIVIAL_CV(is_trivially_destructible, int*, true);
    T_TRIVIAL(is_trivially_destructible, int&, true);
    T_TRIVIAL_CV(is_trivially_destructible, B, false);
    T_TRIVIAL_CV(is_trivially_destructible, C, false);
    T_TRIVIAL_CV(is_trivially_destructible, D, true);
    T_TRIVIAL_CV(is_trivially_destructible, pmo, true);
    T_TRIVIAL_CV(is_trivially_destructible, pmoc, true);
    T_TRIVIAL_CV(is_trivially_destructible, pmov, true);
    T_TRIVIAL_CV(is_trivially_destructible, pmocv, true);
    T_TRIVIAL_CV(is_trivially_destructible, pmf, true);
    T_TRIVIAL_CV(is_trivially_destructible, pmfc, true);
    T_TRIVIAL_CV(is_trivially_destructible, pmfv, true);
    T_TRIVIAL_CV(is_trivially_destructible, pmfcv, true);
    T_TRIVIAL_CV(is_trivially_destructible, arr_t, true);
    T_TRIVIAL_CV(is_trivially_destructible, enum_t, true);
    T_TRIVIAL_CV(is_trivially_destructible, pf, true);
    T_TRIVIAL(is_trivially_destructible, func, false);
    T_TRIVIAL_CV(is_trivially_destructible, void*, true);
}

void test_main() { // test type traits
    t_is_trivially_constructible();
    t_is_trivially_default_constructible();
    t_is_trivially_copy_constructible();
    t_is_trivially_copyable();
    t_is_trivially_move_constructible();

    t_is_trivially_assignable();
    t_is_trivially_copy_assignable();
    t_is_trivially_move_assignable();

    t_is_trivially_destructible();
}
