diff --git a/stl/inc/type_traits b/stl/inc/type_traits index fd27518631c..5b2b160f973 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -721,6 +721,14 @@ struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS is_trivially_copyable : bool_constant< _EXPORT_STD template _NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Ty); +#if _HAS_CXX23 && defined(__clang__) // TRANSITION, GH-5738 tracking VSO-2581622 (MSVC) and VSO-2581623 (EDG) +_EXPORT_STD template +struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS is_implicit_lifetime : bool_constant<__builtin_is_implicit_lifetime(_Ty)> {}; + +_EXPORT_STD template +_NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool is_implicit_lifetime_v = __builtin_is_implicit_lifetime(_Ty); +#endif // ^^^ _HAS_CXX23 && defined(__clang__) ^^^ + _EXPORT_STD template struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS has_virtual_destructor : bool_constant<__has_virtual_destructor(_Ty)> { // determine whether _Ty has a virtual destructor diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 7c1a3f3df44..d10bf011a2b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -396,6 +396,7 @@ // P2604R0 mdspan: data_handle_type, data_handle(), exhaustive // P2613R1 mdspan: empty() // P2652R2 Disallowing User Specialization Of allocator_traits +// P2674R1 is_implicit_lifetime // P2693R1 Formatting thread::id And stacktrace // P2713R1 Escaping Improvements In std::format // P2763R1 Fixing layout_stride's Default Constructor For Fully Static Extents @@ -1823,36 +1824,41 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_generator 202207L #define __cpp_lib_invoke_r 202106L #define __cpp_lib_ios_noreplace 202207L -#define __cpp_lib_is_scoped_enum 202011L -#define __cpp_lib_mdspan 202207L -#define __cpp_lib_move_only_function 202110L -#define __cpp_lib_out_ptr 202311L -#define __cpp_lib_print 202406L -#define __cpp_lib_ranges_as_const 202311L -#define __cpp_lib_ranges_as_rvalue 202207L -#define __cpp_lib_ranges_cartesian_product 202207L -#define __cpp_lib_ranges_chunk 202202L -#define __cpp_lib_ranges_chunk_by 202202L -#define __cpp_lib_ranges_contains 202207L -#define __cpp_lib_ranges_enumerate 202302L -#define __cpp_lib_ranges_find_last 202207L -#define __cpp_lib_ranges_fold 202207L -#define __cpp_lib_ranges_iota 202202L -#define __cpp_lib_ranges_join_with 202202L -#define __cpp_lib_ranges_repeat 202207L -#define __cpp_lib_ranges_slide 202202L -#define __cpp_lib_ranges_starts_ends_with 202106L -#define __cpp_lib_ranges_stride 202207L -#define __cpp_lib_ranges_to_container 202202L -#define __cpp_lib_ranges_zip 202110L -#define __cpp_lib_spanstream 202106L -#define __cpp_lib_stacktrace 202011L -#define __cpp_lib_stdatomic_h 202011L -#define __cpp_lib_string_contains 202011L -#define __cpp_lib_string_resize_and_overwrite 202110L -#define __cpp_lib_to_underlying 202102L -#define __cpp_lib_tuple_like 202207L -#define __cpp_lib_unreachable 202202L + +#ifdef __clang__ // TRANSITION, GH-5738 tracking VSO-2581622 (MSVC) and VSO-2581623 (EDG) +#define __cpp_lib_is_implicit_lifetime 202302L +#endif // ^^^ no workaround ^^^ + +#define __cpp_lib_is_scoped_enum 202011L +#define __cpp_lib_mdspan 202207L +#define __cpp_lib_move_only_function 202110L +#define __cpp_lib_out_ptr 202311L +#define __cpp_lib_print 202406L +#define __cpp_lib_ranges_as_const 202311L +#define __cpp_lib_ranges_as_rvalue 202207L +#define __cpp_lib_ranges_cartesian_product 202207L +#define __cpp_lib_ranges_chunk 202202L +#define __cpp_lib_ranges_chunk_by 202202L +#define __cpp_lib_ranges_contains 202207L +#define __cpp_lib_ranges_enumerate 202302L +#define __cpp_lib_ranges_find_last 202207L +#define __cpp_lib_ranges_fold 202207L +#define __cpp_lib_ranges_iota 202202L +#define __cpp_lib_ranges_join_with 202202L +#define __cpp_lib_ranges_repeat 202207L +#define __cpp_lib_ranges_slide 202202L +#define __cpp_lib_ranges_starts_ends_with 202106L +#define __cpp_lib_ranges_stride 202207L +#define __cpp_lib_ranges_to_container 202202L +#define __cpp_lib_ranges_zip 202110L +#define __cpp_lib_spanstream 202106L +#define __cpp_lib_stacktrace 202011L +#define __cpp_lib_stdatomic_h 202011L +#define __cpp_lib_string_contains 202011L +#define __cpp_lib_string_resize_and_overwrite 202110L +#define __cpp_lib_to_underlying 202102L +#define __cpp_lib_tuple_like 202207L +#define __cpp_lib_unreachable 202202L #endif // _HAS_CXX23 // macros with language mode sensitivity diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index d61fbd35863..edf67dce1fb 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -61,6 +61,9 @@ std/language.support/support.exception/except.nested/ctor_default.pass.cpp:2 SKI # SKIPPED because this is ARM64EC-specific. std/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp:2 SKIPPED +# LLVM-160627: [libc++][test] Guard non-guaranteed implicit-lifetime-ness cases with _LIBCPP_VERSION +std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:2 FAIL + # Non-Standard regex behavior. # "It seems likely that the test is still non-conforming due to how libc++ handles the 'w' character class." std/re/re.traits/lookup_classname.pass.cpp FAIL @@ -565,9 +568,6 @@ std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary. std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp:0 FAIL std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp:1 FAIL -# P2674R1 is_implicit_lifetime -std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp FAIL - # P2944R3 Comparisons For reference_wrapper # Add 'std-at-least-c++26' to tests/utils/stl/test/tests.py when beginning work on C++26. std/utilities/function.objects/refwrap/refwrap.comparisons/compare.three_way.refwrap.const_ref.pass.cpp FAIL @@ -583,7 +583,9 @@ std/utilities/optional/optional.iterator/iterator.pass.cpp FAIL # *** MISSING COMPILER FEATURES *** -# None! +# VSO-2581622 C1XX should implement `__builtin_is_implicit_lifetime` +std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:0 FAIL +std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:1 FAIL # *** MISSING LWG ISSUE RESOLUTIONS *** diff --git a/tests/std/test.lst b/tests/std/test.lst index 247308b4cbc..2cdac46d848 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -707,6 +707,7 @@ tests\P2510R3_text_formatting_pointers tests\P2517R1_apply_conditional_noexcept tests\P2538R1_adl_proof_std_projected tests\P2609R3_relaxing_ranges_just_a_smidge +tests\P2674R1_is_implicit_lifetime tests\P2693R1_ostream_and_thread_id tests\P2693R1_text_formatting_header_stacktrace tests\P2693R1_text_formatting_header_thread diff --git a/tests/std/tests/P2674R1_is_implicit_lifetime/env.lst b/tests/std/tests/P2674R1_is_implicit_lifetime/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P2674R1_is_implicit_lifetime/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/P2674R1_is_implicit_lifetime/test.compile.pass.cpp b/tests/std/tests/P2674R1_is_implicit_lifetime/test.compile.pass.cpp new file mode 100644 index 00000000000..6c4ccd8955d --- /dev/null +++ b/tests/std/tests/P2674R1_is_implicit_lifetime/test.compile.pass.cpp @@ -0,0 +1,180 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +using namespace std; + +enum UnscopedEnum { Enumerator }; +enum class ScopedEnum { Enumerator2 }; +class IncompleteClass; +struct TrivialClass {}; +struct DefaultedDestructorClass { + ~DefaultedDestructorClass() = default; +}; +struct DeletedDestructorClass { + ~DeletedDestructorClass() = delete; +}; +struct UserProvidedDestructorClass { + ~UserProvidedDestructorClass() {} +}; +struct StringAggregateWithImplicitlyDeclaredDestructor { + string juliette_andromeda_meow; + string clarissa_melpomene_meow; +}; +struct StringAggregateWithUserProvidedDestructor { + string chaos_engine_one; + string chaos_engine_two; + ~StringAggregateWithUserProvidedDestructor() {} +}; + +class NonAggregateWithTrivialCtorAndTrivialDtor { +public: + NonAggregateWithTrivialCtorAndTrivialDtor() = default; + ~NonAggregateWithTrivialCtorAndTrivialDtor() = default; + + NonAggregateWithTrivialCtorAndTrivialDtor(const NonAggregateWithTrivialCtorAndTrivialDtor&) = delete; + NonAggregateWithTrivialCtorAndTrivialDtor& operator=(const NonAggregateWithTrivialCtorAndTrivialDtor&) = delete; + + void set_num(int x) { + num = x; + } + int get_num() const { + return num; + } + +private: + int num; +}; + +class NonAggregateWithNonTrivialCtor { +public: + NonAggregateWithNonTrivialCtor() = default; + ~NonAggregateWithNonTrivialCtor() = default; + + NonAggregateWithNonTrivialCtor(const NonAggregateWithNonTrivialCtor&) = delete; + NonAggregateWithNonTrivialCtor& operator=(const NonAggregateWithNonTrivialCtor&) = delete; + + void set_num(int x) { + num = x; + } + int get_num() const { + return num; + } + +private: + int num{0}; // default member initializer => non-trivial default constructor, N5014 [class.default.ctor]/3.2 +}; + +class NonAggregateWithUserProvidedCtor { +public: + NonAggregateWithUserProvidedCtor() {} + ~NonAggregateWithUserProvidedCtor() = default; + + NonAggregateWithUserProvidedCtor(const NonAggregateWithUserProvidedCtor&) = delete; + NonAggregateWithUserProvidedCtor& operator=(const NonAggregateWithUserProvidedCtor&) = delete; + + void set_num(int x) { + num = x; + } + int get_num() const { + return num; + } + +private: + int num; +}; + +class NonAggregateWithDeletedDtor { +public: + NonAggregateWithDeletedDtor() = default; + ~NonAggregateWithDeletedDtor() = delete; + + NonAggregateWithDeletedDtor(const NonAggregateWithDeletedDtor&) = delete; + NonAggregateWithDeletedDtor& operator=(const NonAggregateWithDeletedDtor&) = delete; + + void set_num(int x) { + num = x; + } + int get_num() const { + return num; + } + +private: + int num; +}; + +class NonAggregateWithUserProvidedDtor { +public: + NonAggregateWithUserProvidedDtor() = default; + ~NonAggregateWithUserProvidedDtor() {} + + NonAggregateWithUserProvidedDtor(const NonAggregateWithUserProvidedDtor&) = delete; + NonAggregateWithUserProvidedDtor& operator=(const NonAggregateWithUserProvidedDtor&) = delete; + + void set_num(int x) { + num = x; + } + int get_num() const { + return num; + } + +private: + int num; +}; + +#ifdef __cpp_lib_is_implicit_lifetime +template +constexpr bool test_implicit_lifetime = is_implicit_lifetime_v == Val && is_implicit_lifetime::value == Val; +template +constexpr bool test_implicit_lifetime_cv = test_implicit_lifetime // + && test_implicit_lifetime // + && test_implicit_lifetime // + && test_implicit_lifetime; + +// Scalar types, N5014 [basic.types.general]/9 +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); + +// Implicit-lifetime class types, N5014 [class.prop]/16: +// "A class S is an implicit-lifetime class if +// - it is an aggregate whose destructor is not user-provided or +// - it has at least one trivial eligible constructor and a trivial, non-deleted destructor." +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +#ifndef __clang__ // TRANSITION, LLVM-160610 +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +#endif // ^^^ no workaround ^^^ +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); + +// Arrays +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime_cv); + +static_assert(test_implicit_lifetime_cv); +static_assert(test_implicit_lifetime); +static_assert(test_implicit_lifetime); +static_assert(test_implicit_lifetime); +static_assert(test_implicit_lifetime); +#endif // ^^^ defined(__cpp_lib_is_implicit_lifetime) ^^^ 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 028d8d68a3a..9402abdf299 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 @@ -545,6 +545,12 @@ STATIC_ASSERT(__cpp_lib_is_constant_evaluated == 201811L); STATIC_ASSERT(__cpp_lib_is_final == 201402L); +#if _HAS_CXX23 && defined(__clang__) // TRANSITION, GH-5738 tracking VSO-2581622 (MSVC) and VSO-2581623 (EDG) +STATIC_ASSERT(__cpp_lib_is_implicit_lifetime == 202302L); +#elif defined(__cpp_lib_is_implicit_lifetime) +#error __cpp_lib_is_implicit_lifetime is defined +#endif + #if _HAS_CXX17 STATIC_ASSERT(__cpp_lib_is_invocable == 201703L); #elif defined(__cpp_lib_is_invocable)