//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // _Tp* __constexpr_memmove(_Tp* __dest, _Up* __src, __element_count __n); // // General tests for __constexpr_memmove. // // In particular, we try to ensure that __constexpr_memmove behaves like // __builtin_memmove as closely as possible. This means that it produces the // same effect, but also that it has the same type requirements. // // __builtin_memmove only requires that the types are TriviallyCopyable // (which is interestingly different from both is_trivially_XXX_constructible // and is_trivially_XXX_assignable), so we use some funky types to test these // corner cases. #include <__cxx03/__string/constexpr_c_functions.h> #include #include #include #include "test_macros.h" // The following types are all TriviallyCopyable, but they are not all // trivially_{copy,move}_{constructible,assignable}. TriviallyCopyable // guarantees that the type is *at least* one of the four, but no more // than that. struct CopyConstructible { CopyConstructible() = default; int value = 0; CopyConstructible(const CopyConstructible&) = default; CopyConstructible(CopyConstructible&&) = delete; CopyConstructible& operator=(const CopyConstructible&) = delete; CopyConstructible& operator=(CopyConstructible&&) = delete; }; struct MoveConstructible { MoveConstructible() = default; int value = 0; MoveConstructible(const MoveConstructible&) = delete; MoveConstructible(MoveConstructible&&) = default; MoveConstructible& operator=(const MoveConstructible&) = delete; MoveConstructible& operator=(MoveConstructible&&) = delete; }; struct CopyAssignable { CopyAssignable() = default; int value = 0; CopyAssignable(const CopyAssignable&) = delete; CopyAssignable(CopyAssignable&&) = delete; CopyAssignable& operator=(const CopyAssignable&) = default; CopyAssignable& operator=(CopyAssignable&&) = delete; }; struct MoveAssignable { MoveAssignable() = default; int value = 0; MoveAssignable(const MoveAssignable&) = delete; MoveAssignable(MoveAssignable&&) = delete; MoveAssignable& operator=(const MoveAssignable&) = delete; MoveAssignable& operator=(MoveAssignable&&) = default; }; template TEST_CONSTEXPR_CXX14 void test_user_defined_types() { static_assert(std::is_trivially_copyable::value, "test the test"); static_assert(std::is_trivially_copyable::value, "test the test"); // Note that we can't just initialize with an initializer list since some of the types we use here // are not copy-constructible, which is required in pre-C++20 Standards for that syntax to work. Source src[3]; src[0].value = 1; src[1].value = 2; src[2].value = 3; Dest dst[3]; dst[0].value = 111; dst[1].value = 111; dst[2].value = 111; Dest* result = std::__constexpr_memmove(dst, src, std::__element_count(3)); assert(result == dst); assert(dst[0].value == 1); assert(dst[1].value == 2); assert(dst[2].value == 3); } template TEST_CONSTEXPR_CXX14 void test_builtin_types() { Source src[3] = {1, 2, 3}; Dest dst[3] = {111, 111, 111}; Dest* result = std::__constexpr_memmove(dst, src, std::__element_count(3)); assert(result == dst); assert(dst[0] == 1); assert(dst[1] == 2); assert(dst[2] == 3); } template TEST_CONSTEXPR_CXX14 void test_pointer_types() { ObjectType objs[3] = {1, 2, 3}; SourcePtr src[3] = {objs + 0, objs + 1, objs + 2}; DestPtr dst[3] = {nullptr, nullptr, nullptr}; DestPtr* result = std::__constexpr_memmove(dst, src, std::__element_count(3)); assert(result == dst); assert(dst[0] == objs + 0); assert(dst[1] == objs + 1); assert(dst[2] == objs + 2); } TEST_CONSTEXPR_CXX14 bool test() { test_user_defined_types(); test_user_defined_types(); test_user_defined_types(); test_user_defined_types(); test_builtin_types(); test_builtin_types(); test_builtin_types(); test_builtin_types(); test_builtin_types(); // Cross-type test_builtin_types(); test_builtin_types(); test_builtin_types(); test_builtin_types(); test_pointer_types(); test_pointer_types(); test_pointer_types(); test_pointer_types(); test_pointer_types(); return true; } int main(int, char**) { test(); #if TEST_STD_VER >= 14 static_assert(test(), ""); #endif return 0; }