From c8120cd4b02fc21057457a9d64ebe9ce432d200d Mon Sep 17 00:00:00 2001 From: Mahmoud Saleh <12202790+MahmoudGSaleh@users.noreply.github.com> Date: Tue, 19 Jan 2021 13:44:27 -0800 Subject: [PATCH 1/9] Draft implementation of P0466R5 Layout-Compatibility And Pointer-Interconvertibility Traits --- stl/inc/type_traits | 30 +++ stl/inc/yvals_core.h | 2 + .../env.lst | 4 + .../test.cpp | 179 ++++++++++++++++++ 4 files changed, 215 insertions(+) create mode 100644 tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/env.lst create mode 100644 tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp diff --git a/stl/inc/type_traits b/stl/inc/type_traits index c1a030758bb..86943f3200b 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -1804,6 +1804,36 @@ inline constexpr bool is_nothrow_invocable_r_v = _Select_invoke_traits<_Callable, _Args...>::template _Is_nothrow_invocable_r<_Rx>::value; #endif // _HAS_CXX17 +#if _HAS_CXX20 +// STRUCT TEMPLATE is_layout_compatible +template +struct is_layout_compatible : bool_constant<__builtin_is_layout_compatible(_Ty1, _Ty2)> {}; + +template +inline constexpr bool is_layout_compatible_v = __builtin_is_layout_compatible(_Ty1, _Ty2); + +// STRUCT TEMPLATE is_pointer_interconvertible_base_of +template +struct is_pointer_interconvertible_base_of + : bool_constant<__builtin_is_pointer_interconvertible_base_of(_Base, _Derived)> {}; + +template +inline constexpr bool is_pointer_interconvertible_base_of_v = __builtin_is_pointer_interconvertible_base_of( + _Base, _Derived); + +// STRUCT TEMPLATE is_pointer_interconvertible_with_class +template +inline constexpr bool is_pointer_interconvertible_with_class(_ObjTy _Sty::*_Pm) noexcept { + return __builtin_is_pointer_interconvertible_with_class(_Sty, _Pm); +} + +// STRUCT TEMPLATE is_corresponding_member +template +inline constexpr bool is_corresponding_member(_ObjTy1 _Sty1::*_Pm1, _ObjTy2 _Sty2::*_Pm2) noexcept { + return __builtin_is_corresponding_member(_Sty1, _Sty2, _Pm1, _Pm2); +} +#endif // _HAS_CXX20 + // ALIAS TEMPLATE _Weak_types template struct _Function_args {}; // determine whether _Ty is a function diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 28011748cb5..fe7ed554ca6 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1207,7 +1207,9 @@ #define __cpp_lib_integer_comparison_functions 202002L #define __cpp_lib_interpolate 201902L #define __cpp_lib_is_constant_evaluated 201811L +#define __cpp_lib_is_layout_compatible 202101L #define __cpp_lib_is_nothrow_convertible 201806L +#define __cpp_lib_is_pointer_interconvertible 202101L #define __cpp_lib_jthread 201911L #define __cpp_lib_latch 201907L #define __cpp_lib_list_remove_return_type 201806L diff --git a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/env.lst b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp new file mode 100644 index 00000000000..ee1cb6216dd --- /dev/null +++ b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp @@ -0,0 +1,179 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include +#include +#include + +using namespace std; + +#define ASSERT(...) assert((__VA_ARGS__)) + +constexpr bool test() { + + // is_layout_compatible tests + { + struct S { + int v1; + int v2; + }; + + struct S1 { + S s1; + int v3; + }; + + struct S2 { + S s1; + int v2; + }; + + struct S3 { + S s1; + int v2; + int v3; + }; + + enum E1 { e1, e2, e3 }; + + enum E2 : int { e4, e5, e6 }; + + enum E3 : unsigned int { e7, e8, e9 }; + + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + + ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); + } + + // is_pointer_interconvertible_base_of tests + { + class A {}; + class B : public A {}; + class C : public A { + int : 0; + }; +// Disable warning C4408: anonymous union did not declare any data members +#pragma warning(push) +#pragma warning(disable : 4408) + class D : public A { + union {}; + }; +#pragma warning(pop) + class E : public A { + int v1 = 2; + }; + + class A1 : public A {}; + class A2 : public A {}; + class A3 : public A2 {}; + class A4 : A1, A3 {}; + + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + + ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); + } + + // is_corresponding_member tests + { + struct S1 { + int v1; + int v2; + }; + + struct S2 { + int v1; + int v2; + }; + + struct S3 { + int v1; + int v2; + int v3; + }; + + struct S4 { + char v1; + int v2; + int v3; + }; + + // Same member - same class + ASSERT(is_corresponding_member(&S1::v1, &S1::v1)); + ASSERT(is_corresponding_member(&S1::v2, &S1::v2)); + + // Different member - same class + ASSERT(!is_corresponding_member(&S1::v1, &S1::v2)); + ASSERT(!is_corresponding_member(&S1::v2, &S1::v1)); + + // Same member - different class (layout compatible) + ASSERT(is_corresponding_member(&S1::v1, &S2::v1)); + ASSERT(is_corresponding_member(&S1::v2, &S2::v2)); + + // Same member - different class (layout compatible) + ASSERT(is_corresponding_member(&S1::v1, &S3::v1)); + ASSERT(is_corresponding_member(&S1::v2, &S3::v2)); + + // Different member - different class (layout compatible) + ASSERT(!is_corresponding_member(&S1::v1, &S2::v2)); + ASSERT(!is_corresponding_member(&S1::v2, &S2::v1)); + + // Same member - different class (not layout compatible) + ASSERT(!is_corresponding_member(&S1::v1, &S4::v1)); + ASSERT(!is_corresponding_member(&S1::v2, &S4::v2)); + + // Same member - different class (not layout compatible) + ASSERT(!is_corresponding_member(&S3::v1, &S4::v1)); + ASSERT(!is_corresponding_member(&S3::v2, &S4::v2)); + } + + // is_pointer_interconvertible_with_class tests + { + // A standard-layout class + struct A { + int a; + }; + + // A standard-layout class + struct B { + int b; + }; + + // Not a standard-layout class + struct C : public A, public B {}; + + // Succeeds because, despite its appearance, &C::b has type: "pointer to + // member of B of type int." + ASSERT(is_pointer_interconvertible_with_class(&C::b)); + + // Forces the use of class C, and fails. + ASSERT(!is_pointer_interconvertible_with_class(&C::b)); + + // Succeeds because, despite appearances, &C::a and &C::b have types: + // "pointer to member of A of type int" and + // "pointer to member of B of type int," respectively. + ASSERT(is_corresponding_member(&C::a, &C::b)); + + // Forces the use of class C, and fails + ASSERT(!is_corresponding_member(&C::a, &C::b)); + } + return true; +} + +int main() { + + static_assert(test()); + test(); +} From 33c80cdc699f3201a6cec1b95ce86e6ec8097ede Mon Sep 17 00:00:00 2001 From: Mahmoud Saleh <12202790+MahmoudGSaleh@users.noreply.github.com> Date: Thu, 21 Jan 2021 22:46:12 -0800 Subject: [PATCH 2/9] Updates to PR based on feedback * Fix functions declarations * Add feature test macros tests * Update tests --- stl/inc/type_traits | 18 +-- stl/inc/yvals_core.h | 9 +- .../test.cpp | 118 ++++++++++++------ .../test.compile.pass.cpp | 41 ++++++ 4 files changed, 135 insertions(+), 51 deletions(-) diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 86943f3200b..ba19106d379 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -1805,6 +1805,7 @@ inline constexpr bool is_nothrow_invocable_r_v = #endif // _HAS_CXX17 #if _HAS_CXX20 +#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed // STRUCT TEMPLATE is_layout_compatible template struct is_layout_compatible : bool_constant<__builtin_is_layout_compatible(_Ty1, _Ty2)> {}; @@ -1821,17 +1822,18 @@ template inline constexpr bool is_pointer_interconvertible_base_of_v = __builtin_is_pointer_interconvertible_base_of( _Base, _Derived); -// STRUCT TEMPLATE is_pointer_interconvertible_with_class -template -inline constexpr bool is_pointer_interconvertible_with_class(_ObjTy _Sty::*_Pm) noexcept { - return __builtin_is_pointer_interconvertible_with_class(_Sty, _Pm); +// FUNCTION TEMPLATE is_pointer_interconvertible_with_class +template +_NODISCARD constexpr bool is_pointer_interconvertible_with_class(_MemberTy _ClassTy::*_Pm) noexcept { + return __builtin_is_pointer_interconvertible_with_class(_ClassTy, _Pm); } -// STRUCT TEMPLATE is_corresponding_member -template -inline constexpr bool is_corresponding_member(_ObjTy1 _Sty1::*_Pm1, _ObjTy2 _Sty2::*_Pm2) noexcept { - return __builtin_is_corresponding_member(_Sty1, _Sty2, _Pm1, _Pm2); +// FUNCTION TEMPLATE is_corresponding_member +template +_NODISCARD constexpr bool is_corresponding_member(_MemberTy1 _ClassTy1::*_Pm1, _MemberTy2 _ClassTy2::*_Pm2) noexcept { + return __builtin_is_corresponding_member(_ClassTy1, _ClassTy2, _Pm1, _Pm2); } +#endif // __clang #endif // _HAS_CXX20 // ALIAS TEMPLATE _Weak_types diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index fe7ed554ca6..fb52b19c574 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -145,6 +145,7 @@ // P0457R2 starts_with()/ends_with() For basic_string/basic_string_view // P0458R2 contains() For Ordered And Unordered Associative Containers // P0463R1 endian +// P0466R5 Layout-compatibility and Pointer-interconvertibility Traits // P0476R2 bit_cast // P0482R6 Library Support For char8_t // (mbrtoc8 and c8rtomb not yet implemented) @@ -1207,9 +1208,13 @@ #define __cpp_lib_integer_comparison_functions 202002L #define __cpp_lib_interpolate 201902L #define __cpp_lib_is_constant_evaluated 201811L -#define __cpp_lib_is_layout_compatible 202101L +#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#define __cpp_lib_is_layout_compatible 201907L +#endif // __clang__ #define __cpp_lib_is_nothrow_convertible 201806L -#define __cpp_lib_is_pointer_interconvertible 202101L +#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#define __cpp_lib_is_pointer_interconvertible 201907L +#endif // __clang__ #define __cpp_lib_jthread 201911L #define __cpp_lib_latch 201907L #define __cpp_lib_list_remove_return_type 201806L diff --git a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp index ee1cb6216dd..29481e34879 100644 --- a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp +++ b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp @@ -1,51 +1,87 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include -#include #include using namespace std; #define ASSERT(...) assert((__VA_ARGS__)) -constexpr bool test() { +constexpr bool test() { +#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed // is_layout_compatible tests { - struct S { + struct S0 { int v1; int v2; }; struct S1 { - S s1; + S0 s1; int v3; }; struct S2 { - S s1; + S0 s1; int v2; }; struct S3 { - S s1; + S0 s1; int v2; int v3; }; - enum E1 { e1, e2, e3 }; + struct S4 { + int v1; - enum E2 : int { e4, e5, e6 }; + private: + int v2; + }; + + struct S5 { + int v1; + + private: + int v2; + }; - enum E3 : unsigned int { e7, e8, e9 }; + + const struct S6 { + int v1; + int v2; + }; + + volatile struct S7 { + int v1; + int v2; + }; + + enum E1 { e1, e2, e3, e4 }; + enum E2 : int { e5 }; + enum E3 : unsigned int { e6, e7, e8 }; + enum class E4 : unsigned int { no, yes }; + enum class E5 { zero, fortytwo = 42 }; + const enum E6 : int {}; + volatile enum E7 : int {}; ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); ASSERT(!is_layout_compatible_v); ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); } // is_pointer_interconvertible_base_of tests @@ -62,28 +98,30 @@ constexpr bool test() { union {}; }; #pragma warning(pop) - class E : public A { - int v1 = 2; - }; + const class E : public A { int v1 = 2; }; + volatile class F : public A { int v1 = 2; }; class A1 : public A {}; class A2 : public A {}; class A3 : public A2 {}; - class A4 : A1, A3 {}; + class A4 : public A1, public A3 {}; ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); - ASSERT(!is_pointer_interconvertible_base_of_v); ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); } // is_corresponding_member tests @@ -110,70 +148,68 @@ constexpr bool test() { int v3; }; - // Same member - same class + struct S5 { + int v1; + int v2; + void* v3; + }; + + struct S6 { + int v1; + int v2; + double v3; + }; + ASSERT(is_corresponding_member(&S1::v1, &S1::v1)); ASSERT(is_corresponding_member(&S1::v2, &S1::v2)); - - // Different member - same class ASSERT(!is_corresponding_member(&S1::v1, &S1::v2)); ASSERT(!is_corresponding_member(&S1::v2, &S1::v1)); - - // Same member - different class (layout compatible) ASSERT(is_corresponding_member(&S1::v1, &S2::v1)); ASSERT(is_corresponding_member(&S1::v2, &S2::v2)); - - // Same member - different class (layout compatible) ASSERT(is_corresponding_member(&S1::v1, &S3::v1)); ASSERT(is_corresponding_member(&S1::v2, &S3::v2)); + ASSERT(is_corresponding_member(&S5::v1, &S6::v1)); + ASSERT(is_corresponding_member(&S5::v2, &S6::v2)); - // Different member - different class (layout compatible) ASSERT(!is_corresponding_member(&S1::v1, &S2::v2)); ASSERT(!is_corresponding_member(&S1::v2, &S2::v1)); - - // Same member - different class (not layout compatible) ASSERT(!is_corresponding_member(&S1::v1, &S4::v1)); ASSERT(!is_corresponding_member(&S1::v2, &S4::v2)); - - // Same member - different class (not layout compatible) ASSERT(!is_corresponding_member(&S3::v1, &S4::v1)); ASSERT(!is_corresponding_member(&S3::v2, &S4::v2)); + ASSERT(!is_corresponding_member(&S5::v1, &S6::v2)); + ASSERT(!is_corresponding_member(&S5::v2, &S6::v1)); + ASSERT(!is_corresponding_member(&S5::v3, &S6::v3)); } // is_pointer_interconvertible_with_class tests { - // A standard-layout class struct A { int a; }; - // A standard-layout class struct B { int b; }; - // Not a standard-layout class struct C : public A, public B {}; - // Succeeds because, despite its appearance, &C::b has type: "pointer to - // member of B of type int." - ASSERT(is_pointer_interconvertible_with_class(&C::b)); + union U { + int v1; + char v2; + }; - // Forces the use of class C, and fails. + ASSERT(is_pointer_interconvertible_with_class(&C::b)); ASSERT(!is_pointer_interconvertible_with_class(&C::b)); - // Succeeds because, despite appearances, &C::a and &C::b have types: - // "pointer to member of A of type int" and - // "pointer to member of B of type int," respectively. - ASSERT(is_corresponding_member(&C::a, &C::b)); - - // Forces the use of class C, and fails - ASSERT(!is_corresponding_member(&C::a, &C::b)); + ASSERT(is_pointer_interconvertible_with_class(&U::v1)); + ASSERT(is_pointer_interconvertible_with_class(&U::v2)); } +#endif // __clang__ return true; } int main() { - static_assert(test()); test(); } diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 9a6cd10c972..00e76723778 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -864,6 +864,27 @@ STATIC_ASSERT(__cpp_lib_is_nothrow_convertible == 201806L); #endif #endif +#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#if _HAS_CXX20 +#ifndef __cpp_lib_is_layout_compatible +#error __cpp_lib_is_layout_compatible is not defined +#elif __cpp_lib_is_layout_compatible != 201907L +#error __cpp_lib_is_layout_compatible is not 201907L +#else +STATIC_ASSERT(__cpp_lib_is_layout_compatible == 201907L); +#endif +#else +#ifdef __cpp_lib_is_layout_compatible +#error __cpp_lib_is_layout_compatible is defined +#endif +#endif +#else +#ifdef __cpp_lib_is_layout_compatible +#error __cpp_lib_is_layout_compatible is defined +#endif +#endif + + #ifndef __cpp_lib_is_null_pointer #error __cpp_lib_is_null_pointer is not defined #elif __cpp_lib_is_null_pointer != 201309L @@ -872,6 +893,26 @@ STATIC_ASSERT(__cpp_lib_is_nothrow_convertible == 201806L); STATIC_ASSERT(__cpp_lib_is_null_pointer == 201309L); #endif +#if _HAS_CXX20 +#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#ifndef __cpp_lib_is_pointer_interconvertible +#error __cpp_lib_is_pointer_interconvertible is not defined +#elif __cpp_lib_is_pointer_interconvertible != 201907L +#error __cpp_lib_is_pointer_interconvertible is not 201907L +#else +STATIC_ASSERT(__cpp_lib_is_pointer_interconvertible == 201907L); +#endif +#else +#ifdef __cpp_lib_is_pointer_interconvertible +#error __cpp_lib_is_pointer_interconvertible is defined +#endif +#endif +#else +#ifdef __cpp_lib_is_pointer_interconvertible +#error __cpp_lib_is_pointer_interconvertible is defined +#endif +#endif + #if _HAS_CXX17 #ifndef __cpp_lib_is_swappable #error __cpp_lib_is_swappable is not defined From 54ce30d5aee07a2da047f2121e30157c52b63d30 Mon Sep 17 00:00:00 2001 From: Mahmoud Saleh <12202790+MahmoudGSaleh@users.noreply.github.com> Date: Thu, 21 Jan 2021 22:52:01 -0800 Subject: [PATCH 3/9] Test fixes for consistency --- .../test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp index 29481e34879..5b49331a3e2 100644 --- a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp +++ b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp @@ -192,7 +192,7 @@ constexpr bool test() { int b; }; - struct C : public A, public B {}; + struct C : A, B {}; union U { int v1; From cfbb97f37118de549df17dc914bd46e5748067ab Mon Sep 17 00:00:00 2001 From: Mahmoud Saleh <12202790+MahmoudGSaleh@users.noreply.github.com> Date: Thu, 21 Jan 2021 23:09:19 -0800 Subject: [PATCH 4/9] Fix clang-format issues --- stl/inc/yvals_core.h | 34 +++++++++++-------- .../test.compile.pass.cpp | 2 +- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index fb52b19c574..f547aece218 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1208,25 +1208,29 @@ #define __cpp_lib_integer_comparison_functions 202002L #define __cpp_lib_interpolate 201902L #define __cpp_lib_is_constant_evaluated 201811L + #ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed -#define __cpp_lib_is_layout_compatible 201907L +#define __cpp_lib_is_layout_compatible 201907L #endif // __clang__ -#define __cpp_lib_is_nothrow_convertible 201806L + +#define __cpp_lib_is_nothrow_convertible 201806L + #ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed -#define __cpp_lib_is_pointer_interconvertible 201907L +#define __cpp_lib_is_pointer_interconvertible 201907L #endif // __clang__ -#define __cpp_lib_jthread 201911L -#define __cpp_lib_latch 201907L -#define __cpp_lib_list_remove_return_type 201806L -#define __cpp_lib_math_constants 201907L -#define __cpp_lib_polymorphic_allocator 201902L -#define __cpp_lib_remove_cvref 201711L -#define __cpp_lib_semaphore 201907L -#define __cpp_lib_shift 201806L -#define __cpp_lib_smart_ptr_for_overwrite 202002L -#define __cpp_lib_span 202002L -#define __cpp_lib_ssize 201902L -#define __cpp_lib_starts_ends_with 201711L + +#define __cpp_lib_jthread 201911L +#define __cpp_lib_latch 201907L +#define __cpp_lib_list_remove_return_type 201806L +#define __cpp_lib_math_constants 201907L +#define __cpp_lib_polymorphic_allocator 201902L +#define __cpp_lib_remove_cvref 201711L +#define __cpp_lib_semaphore 201907L +#define __cpp_lib_shift 201806L +#define __cpp_lib_smart_ptr_for_overwrite 202002L +#define __cpp_lib_span 202002L +#define __cpp_lib_ssize 201902L +#define __cpp_lib_starts_ends_with 201711L #ifdef __cpp_lib_concepts // TRANSITION, GH-395 #define __cpp_lib_three_way_comparison 201711L diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 00e76723778..1312b3182d1 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -893,7 +893,7 @@ STATIC_ASSERT(__cpp_lib_is_layout_compatible == 201907L); STATIC_ASSERT(__cpp_lib_is_null_pointer == 201309L); #endif -#if _HAS_CXX20 +#if _HAS_CXX20 #ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed #ifndef __cpp_lib_is_pointer_interconvertible #error __cpp_lib_is_pointer_interconvertible is not defined From 6a8e3e9c4079b28a83e7a01f8b92e140dfdcc840 Mon Sep 17 00:00:00 2001 From: Mahmoud Saleh <12202790+MahmoudGSaleh@users.noreply.github.com> Date: Fri, 22 Jan 2021 12:08:23 -0800 Subject: [PATCH 5/9] Fix BE test failures and cv-qualifiers tests --- stl/inc/type_traits | 2 ++ stl/inc/yvals_core.h | 4 +++ .../test.cpp | 35 ++++++------------- .../test.compile.pass.cpp | 11 ++---- 4 files changed, 19 insertions(+), 33 deletions(-) diff --git a/stl/inc/type_traits b/stl/inc/type_traits index ba19106d379..cae0582bc67 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -1805,6 +1805,7 @@ inline constexpr bool is_nothrow_invocable_r_v = #endif // _HAS_CXX17 #if _HAS_CXX20 +#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed // STRUCT TEMPLATE is_layout_compatible template @@ -1834,6 +1835,7 @@ _NODISCARD constexpr bool is_corresponding_member(_MemberTy1 _ClassTy1::*_Pm1, _ return __builtin_is_corresponding_member(_ClassTy1, _ClassTy2, _Pm1, _Pm2); } #endif // __clang +#endif // __EDG__ #endif // _HAS_CXX20 // ALIAS TEMPLATE _Weak_types diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index f547aece218..3c28c4cdafa 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1209,15 +1209,19 @@ #define __cpp_lib_interpolate 201902L #define __cpp_lib_is_constant_evaluated 201811L +#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed #define __cpp_lib_is_layout_compatible 201907L #endif // __clang__ +#endif // __EDG__ #define __cpp_lib_is_nothrow_convertible 201806L +#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed #define __cpp_lib_is_pointer_interconvertible 201907L #endif // __clang__ +#endif // __EDG__ #define __cpp_lib_jthread 201911L #define __cpp_lib_latch 201907L diff --git a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp index 5b49331a3e2..b47e273c1b6 100644 --- a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp +++ b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp @@ -9,6 +9,7 @@ using namespace std; constexpr bool test() { +#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed // is_layout_compatible tests { @@ -47,35 +48,22 @@ constexpr bool test() { int v2; }; - - const struct S6 { - int v1; - int v2; - }; - - volatile struct S7 { - int v1; - int v2; - }; - enum E1 { e1, e2, e3, e4 }; enum E2 : int { e5 }; enum E3 : unsigned int { e6, e7, e8 }; enum class E4 : unsigned int { no, yes }; enum class E5 { zero, fortytwo = 42 }; - const enum E6 : int {}; - volatile enum E7 : int {}; ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); - ASSERT(is_layout_compatible_v); - ASSERT(is_layout_compatible_v); - ASSERT(is_layout_compatible_v); - ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); ASSERT(!is_layout_compatible_v); ASSERT(!is_layout_compatible_v); @@ -98,9 +86,6 @@ constexpr bool test() { union {}; }; #pragma warning(pop) - const class E : public A { int v1 = 2; }; - volatile class F : public A { int v1 = 2; }; - class A1 : public A {}; class A2 : public A {}; class A3 : public A2 {}; @@ -108,20 +93,19 @@ constexpr bool test() { ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); - ASSERT(is_pointer_interconvertible_base_of_v); - ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); - ASSERT(!is_pointer_interconvertible_base_of_v); ASSERT(!is_pointer_interconvertible_base_of_v); - ASSERT(!is_pointer_interconvertible_base_of_v); ASSERT(!is_pointer_interconvertible_base_of_v); - ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); } // is_corresponding_member tests @@ -206,6 +190,7 @@ constexpr bool test() { ASSERT(is_pointer_interconvertible_with_class(&U::v2)); } #endif // __clang__ +#endif // __EDG__ return true; } diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 1312b3182d1..5f2f8a5a6e4 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -864,8 +864,9 @@ STATIC_ASSERT(__cpp_lib_is_nothrow_convertible == 201806L); #endif #endif -#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed #if _HAS_CXX20 +#ifndef __EDG__ // TRANSITION, VSO-1268984 +#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed #ifndef __cpp_lib_is_layout_compatible #error __cpp_lib_is_layout_compatible is not defined #elif __cpp_lib_is_layout_compatible != 201907L @@ -878,13 +879,9 @@ STATIC_ASSERT(__cpp_lib_is_layout_compatible == 201907L); #error __cpp_lib_is_layout_compatible is defined #endif #endif -#else -#ifdef __cpp_lib_is_layout_compatible -#error __cpp_lib_is_layout_compatible is defined #endif #endif - #ifndef __cpp_lib_is_null_pointer #error __cpp_lib_is_null_pointer is not defined #elif __cpp_lib_is_null_pointer != 201309L @@ -894,6 +891,7 @@ STATIC_ASSERT(__cpp_lib_is_null_pointer == 201309L); #endif #if _HAS_CXX20 +#ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed #ifndef __cpp_lib_is_pointer_interconvertible #error __cpp_lib_is_pointer_interconvertible is not defined @@ -907,9 +905,6 @@ STATIC_ASSERT(__cpp_lib_is_pointer_interconvertible == 201907L); #error __cpp_lib_is_pointer_interconvertible is defined #endif #endif -#else -#ifdef __cpp_lib_is_pointer_interconvertible -#error __cpp_lib_is_pointer_interconvertible is defined #endif #endif From 84083f14d504970ccdbb3e50666a46c12e1b0d9c Mon Sep 17 00:00:00 2001 From: Mahmoud Saleh <12202790+MahmoudGSaleh@users.noreply.github.com> Date: Fri, 22 Jan 2021 16:59:31 -0800 Subject: [PATCH 6/9] Fix ordering of tests in feature_test_macros --- .../test.compile.pass.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 5f2f8a5a6e4..58c4f372ffa 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -850,20 +850,6 @@ STATIC_ASSERT(__cpp_lib_is_invocable == 201703L); #endif #endif -#if _HAS_CXX20 -#ifndef __cpp_lib_is_nothrow_convertible -#error __cpp_lib_is_nothrow_convertible is not defined -#elif __cpp_lib_is_nothrow_convertible != 201806L -#error __cpp_lib_is_nothrow_convertible is not 201806L -#else -STATIC_ASSERT(__cpp_lib_is_nothrow_convertible == 201806L); -#endif -#else -#ifdef __cpp_lib_is_nothrow_convertible -#error __cpp_lib_is_nothrow_convertible is defined -#endif -#endif - #if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, VSO-1268984 #ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed @@ -882,6 +868,20 @@ STATIC_ASSERT(__cpp_lib_is_layout_compatible == 201907L); #endif #endif +#if _HAS_CXX20 +#ifndef __cpp_lib_is_nothrow_convertible +#error __cpp_lib_is_nothrow_convertible is not defined +#elif __cpp_lib_is_nothrow_convertible != 201806L +#error __cpp_lib_is_nothrow_convertible is not 201806L +#else +STATIC_ASSERT(__cpp_lib_is_nothrow_convertible == 201806L); +#endif +#else +#ifdef __cpp_lib_is_nothrow_convertible +#error __cpp_lib_is_nothrow_convertible is defined +#endif +#endif + #ifndef __cpp_lib_is_null_pointer #error __cpp_lib_is_null_pointer is not defined #elif __cpp_lib_is_null_pointer != 201309L From f49d233998707305f03ae81804eccd0ed0c4e2f7 Mon Sep 17 00:00:00 2001 From: Mahmoud Saleh <12202790+MahmoudGSaleh@users.noreply.github.com> Date: Tue, 26 Jan 2021 15:52:58 -0800 Subject: [PATCH 7/9] Apply PR code review feedback - Updated LLVM bug # for adding intrinsics to clang - Added condition for using outdated vs renamed intrinsics - Added new tests per review feedback --- stl/inc/type_traits | 35 +++++- stl/inc/yvals_core.h | 6 +- tests/std/test.lst | 1 + .../test.cpp | 115 +++++++++++++----- .../test.compile.pass.cpp | 4 +- 5 files changed, 121 insertions(+), 40 deletions(-) diff --git a/stl/inc/type_traits b/stl/inc/type_traits index cae0582bc67..2d50aa726cf 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -1806,35 +1806,62 @@ inline constexpr bool is_nothrow_invocable_r_v = #if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, VSO-1268984 -#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#ifndef __clang__ // TRANSITION, LLVM-48860 // STRUCT TEMPLATE is_layout_compatible template -struct is_layout_compatible : bool_constant<__builtin_is_layout_compatible(_Ty1, _Ty2)> {}; +#ifdef _IS_LAYOUT_COMPATIBLE_SUPPORTED +struct is_layout_compatible : bool_constant<__is_layout_compatible(_Ty1, _Ty2)> { +#else // ^^^ _IS_LAYOUT_COMPATIBLE_SUPPORTED / !_IS_LAYOUT_COMPATIBLE_SUPPORTED vvv +struct is_layout_compatible : bool_constant<__builtin_is_layout_compatible(_Ty1, _Ty2)> { +#endif // _IS_LAYOUT_COMPATIBLE_SUPPORTED +}; template +#ifdef _IS_LAYOUT_COMPATIBLE_SUPPORTED +inline constexpr bool is_layout_compatible_v = __is_layout_compatible(_Ty1, _Ty2); +#else // ^^^ _IS_LAYOUT_COMPATIBLE_SUPPORTED / !_IS_LAYOUT_COMPATIBLE_SUPPORTED vvv inline constexpr bool is_layout_compatible_v = __builtin_is_layout_compatible(_Ty1, _Ty2); +#endif // _IS_LAYOUT_COMPATIBLE_SUPPORTED // STRUCT TEMPLATE is_pointer_interconvertible_base_of template struct is_pointer_interconvertible_base_of - : bool_constant<__builtin_is_pointer_interconvertible_base_of(_Base, _Derived)> {}; +#ifdef _IS_LAYOUT_COMPATIBLE_SUPPORTED + : bool_constant<__is_pointer_interconvertible_base_of(_Base, _Derived)> { +}; +#else // ^^^ _IS_LAYOUT_COMPATIBLE_SUPPORTED / !_IS_LAYOUT_COMPATIBLE_SUPPORTED vvv + : bool_constant<__builtin_is_pointer_interconvertible_base_of(_Base, _Derived)> { +}; +#endif // _IS_LAYOUT_COMPATIBLE_SUPPORTED template +#ifdef _IS_LAYOUT_COMPATIBLE_SUPPORTED +inline constexpr bool is_pointer_interconvertible_base_of_v = __is_pointer_interconvertible_base_of(_Base, _Derived); +#else // ^^^ _IS_LAYOUT_COMPATIBLE_SUPPORTED / !_IS_LAYOUT_COMPATIBLE_SUPPORTED vvv inline constexpr bool is_pointer_interconvertible_base_of_v = __builtin_is_pointer_interconvertible_base_of( _Base, _Derived); +#endif // _IS_LAYOUT_COMPATIBLE_SUPPORTED // FUNCTION TEMPLATE is_pointer_interconvertible_with_class template _NODISCARD constexpr bool is_pointer_interconvertible_with_class(_MemberTy _ClassTy::*_Pm) noexcept { +#ifdef _IS_LAYOUT_COMPATIBLE_SUPPORTED + return __is_pointer_interconvertible_with_class(_ClassTy, _Pm); +#else // ^^^ _IS_LAYOUT_COMPATIBLE_SUPPORTED / !_IS_LAYOUT_COMPATIBLE_SUPPORTED vvv return __builtin_is_pointer_interconvertible_with_class(_ClassTy, _Pm); +#endif // _IS_LAYOUT_COMPATIBLE_SUPPORTED } // FUNCTION TEMPLATE is_corresponding_member template _NODISCARD constexpr bool is_corresponding_member(_MemberTy1 _ClassTy1::*_Pm1, _MemberTy2 _ClassTy2::*_Pm2) noexcept { +#ifdef _IS_LAYOUT_COMPATIBLE_SUPPORTED + return __is_corresponding_member(_ClassTy1, _ClassTy2, _Pm1, _Pm2); +#else // ^^^ _IS_LAYOUT_COMPATIBLE_SUPPORTED / !_IS_LAYOUT_COMPATIBLE_SUPPORTED vvv return __builtin_is_corresponding_member(_ClassTy1, _ClassTy2, _Pm1, _Pm2); +#endif // _IS_LAYOUT_COMPATIBLE_SUPPORTED } -#endif // __clang +#endif // __clang__ #endif // __EDG__ #endif // _HAS_CXX20 diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 3c28c4cdafa..964dd68338c 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -145,7 +145,7 @@ // P0457R2 starts_with()/ends_with() For basic_string/basic_string_view // P0458R2 contains() For Ordered And Unordered Associative Containers // P0463R1 endian -// P0466R5 Layout-compatibility and Pointer-interconvertibility Traits +// P0466R5 Layout-Compatibility And Pointer-Interconvertibility Traits // P0476R2 bit_cast // P0482R6 Library Support For char8_t // (mbrtoc8 and c8rtomb not yet implemented) @@ -1210,7 +1210,7 @@ #define __cpp_lib_is_constant_evaluated 201811L #ifndef __EDG__ // TRANSITION, VSO-1268984 -#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#ifndef __clang__ // TRANSITION, LLVM-48860 #define __cpp_lib_is_layout_compatible 201907L #endif // __clang__ #endif // __EDG__ @@ -1218,7 +1218,7 @@ #define __cpp_lib_is_nothrow_convertible 201806L #ifndef __EDG__ // TRANSITION, VSO-1268984 -#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#ifndef __clang__ // TRANSITION, LLVM-48860 #define __cpp_lib_is_pointer_interconvertible 201907L #endif // __clang__ #endif // __EDG__ diff --git a/tests/std/test.lst b/tests/std/test.lst index 3d71f043206..15dae20ad33 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -232,6 +232,7 @@ tests\P0414R2_shared_ptr_for_arrays tests\P0415R1_constexpr_complex tests\P0426R1_constexpr_char_traits tests\P0433R2_deduction_guides +tests\P0466R5_layout_compatibility_and_pointer_interconvertibility_traits tests\P0476R2_bit_cast tests\P0487R1_fixing_operator_shl_basic_istream_char_pointer tests\P0513R0_poisoning_the_hash diff --git a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp index b47e273c1b6..b4316266f46 100644 --- a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp +++ b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp @@ -7,10 +7,15 @@ using namespace std; #define ASSERT(...) assert((__VA_ARGS__)) +struct S { // struct with static type, so declaring global + static int s1; + int v1; + int v2; +}; constexpr bool test() { #ifndef __EDG__ // TRANSITION, VSO-1268984 -#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#ifndef __clang__ // TRANSITION, LLVM-48860 // is_layout_compatible tests { struct S0 { @@ -55,21 +60,34 @@ constexpr bool test() { enum class E5 { zero, fortytwo = 42 }; ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); - ASSERT(is_layout_compatible_v); - ASSERT(is_layout_compatible_v); - ASSERT(is_layout_compatible_v); - ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + + // TRANSITION, VSO-1269781 + // ASSERT(is_layout_compatible_v); + // ASSERT(is_layout_compatible_v); + // ASSERT(is_layout_compatible_v); ASSERT(!is_layout_compatible_v); - ASSERT(!is_layout_compatible_v); - ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); ASSERT(!is_layout_compatible_v); ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); + ASSERT(!is_layout_compatible_v); } // is_pointer_interconvertible_base_of tests @@ -79,17 +97,22 @@ constexpr bool test() { class C : public A { int : 0; }; + class D : public C {}; // Disable warning C4408: anonymous union did not declare any data members #pragma warning(push) #pragma warning(disable : 4408) - class D : public A { + class E : public A { union {}; }; #pragma warning(pop) - class A1 : public A {}; - class A2 : public A {}; - class A3 : public A2 {}; - class A4 : public A1, public A3 {}; + class F : private A {}; // Non-public inheritance + class NS : public B, public C {}; // Non-standard + class I; // Incomplete + + union U { + int i; + char c; + }; ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); @@ -98,14 +121,21 @@ constexpr bool test() { ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); ASSERT(is_pointer_interconvertible_base_of_v); - ASSERT(is_pointer_interconvertible_base_of_v); - ASSERT(is_pointer_interconvertible_base_of_v); - ASSERT(is_pointer_interconvertible_base_of_v); - ASSERT(is_pointer_interconvertible_base_of_v); - - ASSERT(!is_pointer_interconvertible_base_of_v); - ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + ASSERT(is_pointer_interconvertible_base_of_v); + + ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); + ASSERT(!is_pointer_interconvertible_base_of_v); } // is_corresponding_member tests @@ -116,8 +146,8 @@ constexpr bool test() { }; struct S2 { - int v1; - int v2; + int w1; + int w2; }; struct S3 { @@ -144,19 +174,28 @@ constexpr bool test() { double v3; }; + struct S7 { + int f1() { + return 0; + } + }; + + struct NS : S1, S2 {}; // Non-standard + + ASSERT(is_corresponding_member(&S1::v1, &S::v1)); + ASSERT(is_corresponding_member(&S1::v2, &S::v2)); ASSERT(is_corresponding_member(&S1::v1, &S1::v1)); ASSERT(is_corresponding_member(&S1::v2, &S1::v2)); - ASSERT(!is_corresponding_member(&S1::v1, &S1::v2)); - ASSERT(!is_corresponding_member(&S1::v2, &S1::v1)); - ASSERT(is_corresponding_member(&S1::v1, &S2::v1)); - ASSERT(is_corresponding_member(&S1::v2, &S2::v2)); + ASSERT(is_corresponding_member(&S1::v1, &S2::w1)); + ASSERT(is_corresponding_member(&S1::v2, &S2::w2)); ASSERT(is_corresponding_member(&S1::v1, &S3::v1)); ASSERT(is_corresponding_member(&S1::v2, &S3::v2)); ASSERT(is_corresponding_member(&S5::v1, &S6::v1)); ASSERT(is_corresponding_member(&S5::v2, &S6::v2)); - ASSERT(!is_corresponding_member(&S1::v1, &S2::v2)); - ASSERT(!is_corresponding_member(&S1::v2, &S2::v1)); + ASSERT(!is_corresponding_member(&S1::v1, &S1::v2)); + ASSERT(!is_corresponding_member(&S1::v2, &S1::v1)); + ASSERT(!is_corresponding_member(&S1::v2, &S2::w1)); ASSERT(!is_corresponding_member(&S1::v1, &S4::v1)); ASSERT(!is_corresponding_member(&S1::v2, &S4::v2)); ASSERT(!is_corresponding_member(&S3::v1, &S4::v1)); @@ -164,6 +203,10 @@ constexpr bool test() { ASSERT(!is_corresponding_member(&S5::v1, &S6::v2)); ASSERT(!is_corresponding_member(&S5::v2, &S6::v1)); ASSERT(!is_corresponding_member(&S5::v3, &S6::v3)); + ASSERT(!is_corresponding_member(&NS::v1, &NS::w1)); + ASSERT(!is_corresponding_member(&S7::f1, &S7::f1)); + ASSERT(!is_corresponding_member(nullptr, nullptr)); + ASSERT(!is_corresponding_member(&S1::v1, nullptr)); } // is_pointer_interconvertible_with_class tests @@ -176,18 +219,28 @@ constexpr bool test() { int b; }; - struct C : A, B {}; + struct C { + int f1() { + return 0; + } + }; + + struct NS : A, B {}; // Non-standard union U { int v1; char v2; }; - ASSERT(is_pointer_interconvertible_with_class(&C::b)); - ASSERT(!is_pointer_interconvertible_with_class(&C::b)); - + ASSERT(is_pointer_interconvertible_with_class(&A::a)); + ASSERT(is_pointer_interconvertible_with_class(&NS::b)); ASSERT(is_pointer_interconvertible_with_class(&U::v1)); ASSERT(is_pointer_interconvertible_with_class(&U::v2)); + + ASSERT(!is_pointer_interconvertible_with_class(&NS::a)); + ASSERT(!is_pointer_interconvertible_with_class(&NS::b)); + ASSERT(!is_pointer_interconvertible_with_class(&C::f1)); + ASSERT(!is_pointer_interconvertible_with_class(nullptr)); } #endif // __clang__ #endif // __EDG__ diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 58c4f372ffa..db066537944 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -852,7 +852,7 @@ STATIC_ASSERT(__cpp_lib_is_invocable == 201703L); #if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, VSO-1268984 -#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#ifndef __clang__ // TRANSITION, LLVM-48860 #ifndef __cpp_lib_is_layout_compatible #error __cpp_lib_is_layout_compatible is not defined #elif __cpp_lib_is_layout_compatible != 201907L @@ -892,7 +892,7 @@ STATIC_ASSERT(__cpp_lib_is_null_pointer == 201309L); #if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, VSO-1268984 -#ifndef __clang__ // TRANSITION, LLVM-Bug #: To Be Filed +#ifndef __clang__ // TRANSITION, LLVM-48860 #ifndef __cpp_lib_is_pointer_interconvertible #error __cpp_lib_is_pointer_interconvertible is not defined #elif __cpp_lib_is_pointer_interconvertible != 201907L From c115942c6c4d662c2c8303c862712d802bc2a6bb Mon Sep 17 00:00:00 2001 From: Mahmoud Saleh <12202790+MahmoudGSaleh@users.noreply.github.com> Date: Wed, 27 Jan 2021 10:50:46 -0800 Subject: [PATCH 8/9] Apply fixes from feedback comments --- .../test.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp index b4316266f46..1e6da4ac774 100644 --- a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp +++ b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp @@ -7,7 +7,7 @@ using namespace std; #define ASSERT(...) assert((__VA_ARGS__)) -struct S { // struct with static type, so declaring global +struct S { // Must be declared at namespace scope due to static data member static int s1; int v1; int v2; @@ -73,10 +73,11 @@ constexpr bool test() { ASSERT(is_layout_compatible_v); ASSERT(is_layout_compatible_v); - // TRANSITION, VSO-1269781 - // ASSERT(is_layout_compatible_v); - // ASSERT(is_layout_compatible_v); - // ASSERT(is_layout_compatible_v); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1269781 + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); + ASSERT(is_layout_compatible_v); +#endif // TRANSITION, VSO-1269781 ASSERT(!is_layout_compatible_v); ASSERT(!is_layout_compatible_v); @@ -106,7 +107,7 @@ constexpr bool test() { }; #pragma warning(pop) class F : private A {}; // Non-public inheritance - class NS : public B, public C {}; // Non-standard + class NS : public B, public C {}; // Non-standard layout class I; // Incomplete union U { @@ -180,7 +181,7 @@ constexpr bool test() { } }; - struct NS : S1, S2 {}; // Non-standard + struct NS : S1, S2 {}; // Non-standard layout ASSERT(is_corresponding_member(&S1::v1, &S::v1)); ASSERT(is_corresponding_member(&S1::v2, &S::v2)); @@ -225,7 +226,7 @@ constexpr bool test() { } }; - struct NS : A, B {}; // Non-standard + struct NS : A, B {}; // Non-standard layout union U { int v1; From 53a91b190fc9bc77d57ee5e81bd2beb43fb519f8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 29 Jan 2021 15:48:11 -0800 Subject: [PATCH 9/9] static_cast nullptr to use template argument deduction. --- .../test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp index 1e6da4ac774..78309c6cc21 100644 --- a/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp +++ b/tests/std/tests/P0466R5_layout_compatibility_and_pointer_interconvertibility_traits/test.cpp @@ -206,8 +206,8 @@ constexpr bool test() { ASSERT(!is_corresponding_member(&S5::v3, &S6::v3)); ASSERT(!is_corresponding_member(&NS::v1, &NS::w1)); ASSERT(!is_corresponding_member(&S7::f1, &S7::f1)); - ASSERT(!is_corresponding_member(nullptr, nullptr)); - ASSERT(!is_corresponding_member(&S1::v1, nullptr)); + ASSERT(!is_corresponding_member(static_cast(nullptr), static_cast(nullptr))); + ASSERT(!is_corresponding_member(&S1::v1, static_cast(nullptr))); } // is_pointer_interconvertible_with_class tests @@ -241,7 +241,7 @@ constexpr bool test() { ASSERT(!is_pointer_interconvertible_with_class(&NS::a)); ASSERT(!is_pointer_interconvertible_with_class(&NS::b)); ASSERT(!is_pointer_interconvertible_with_class(&C::f1)); - ASSERT(!is_pointer_interconvertible_with_class(nullptr)); + ASSERT(!is_pointer_interconvertible_with_class(static_cast(nullptr))); } #endif // __clang__ #endif // __EDG__