Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
4252d7d
Add is_implicit_lifetime trait for Clang
TymianekPL Apr 27, 2025
28f5f81
Add test
TymianekPL Apr 27, 2025
58464a7
Add feature-test macro
TymianekPL Apr 27, 2025
b5b56f7
move the macro, remove redundant inline keyword
TymianekPL Apr 29, 2025
2162504
Update yvals_core.h
TymianekPL Apr 29, 2025
824c116
Add using namespace std and remove VLA test from the P2674 test suite
TymianekPL Apr 29, 2025
9bd93c2
Update type_traits
TymianekPL Apr 29, 2025
613f407
Update yvals_core.h
TymianekPL Apr 29, 2025
747f4e8
More test passes
TymianekPL May 1, 2025
f2fd537
Remove explicit std resolution path
TymianekPL May 1, 2025
a7ff2f9
Add feature-test test
TymianekPL May 1, 2025
72d311e
Move implementation comment for P2674R1 in yvals_core.h
TymianekPL May 1, 2025
003fe2b
Merge branch 'microsoft:main' into main
TymianekPL Sep 16, 2025
51f5433
[is_implicit_lifetime/test] Fix typos, remove main, rename classes, f…
TymianekPL Sep 16, 2025
011f349
small typo on the test_implicit_lifetime entity
TymianekPL Sep 16, 2025
6b51bf8
format
TymianekPL Sep 16, 2025
b063780
remove weird whitespace from yvals core
TymianekPL Sep 16, 2025
dbd9381
clang-format (test/P2674)
TymianekPL Sep 16, 2025
95d7688
clang-format in VSO_0157762_feature_test_macros
TymianekPL Sep 16, 2025
38db02e
remove new-lines from VSO_0157752
TymianekPL Sep 16, 2025
7814e55
remove new-lines from P2674R1_is_implicit_lifetime
TymianekPL Sep 16, 2025
27a43ca
missing )
TymianekPL Sep 16, 2025
685978e
remove whitespace (why is it being added??)
TymianekPL Sep 16, 2025
b2190d2
Add the missing exclamation mark near fp is_implicit_lifetime test
TymianekPL Sep 16, 2025
2618826
new-lines. again?!
TymianekPL Sep 16, 2025
3b93665
fix the test P2674R1_is_implicit_lifetime
TymianekPL Sep 18, 2025
f4465f6
Merge branch 'main' into gh5445
StephanTLavavej Sep 24, 2025
608cb3b
Clean up paper title.
StephanTLavavej Sep 24, 2025
8d522a2
Sort feature-test macro, cite followup issues for MSVC and EDG.
StephanTLavavej Sep 24, 2025
8b7d0ea
Sort feature-test macro test, cite followup issues for MSVC and EDG.
StephanTLavavej Sep 24, 2025
0470bad
Add new test to test.lst.
StephanTLavavej Sep 24, 2025
507a971
This is a C++23 feature, not C++20.
StephanTLavavej Sep 24, 2025
5b87a91
Apply no_specializations attributes, follow Standard order, add/fix c…
StephanTLavavej Sep 24, 2025
e82c354
Test review, part 1: Minor nitpicks.
StephanTLavavej Sep 24, 2025
8e7f749
Test review, part 2: Consistently test cv-qualifiers.
StephanTLavavej Sep 24, 2025
a8a20cb
Test review, part 3: More scalars, more unbounded arrays, more refere…
StephanTLavavej Sep 24, 2025
8212b8a
Test review, part 4: Expand test coverage of class types, finding a C…
StephanTLavavej Sep 24, 2025
379791e
Update libcxx/expected_results.txt.
StephanTLavavej Sep 24, 2025
6092e93
Make non-aggregates noncopyable to avoid interference from copy ctors.
StephanTLavavej Sep 25, 2025
bd0d861
Cite LLVM-160627.
StephanTLavavej Sep 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions stl/inc/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,14 @@ struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS is_trivially_copyable : bool_constant<
_EXPORT_STD template <class _Ty>
_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 <class _Ty>
struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS is_implicit_lifetime : bool_constant<__builtin_is_implicit_lifetime(_Ty)> {};

_EXPORT_STD template <class _Ty>
_NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool is_implicit_lifetime_v = __builtin_is_implicit_lifetime(_Ty);
#endif // ^^^ _HAS_CXX23 && defined(__clang__) ^^^

_EXPORT_STD template <class _Ty>
struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS has_virtual_destructor : bool_constant<__has_virtual_destructor(_Ty)> {
// determine whether _Ty has a virtual destructor
Expand Down
66 changes: 36 additions & 30 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 ***
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P2674R1_is_implicit_lifetime/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
180 changes: 180 additions & 0 deletions tests/std/tests/P2674R1_is_implicit_lifetime/test.compile.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cstddef>
#include <string>
#include <type_traits>
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 <bool Val, typename T>
constexpr bool test_implicit_lifetime = is_implicit_lifetime_v<T> == Val && is_implicit_lifetime<T>::value == Val;
template <bool Val, typename T>
constexpr bool test_implicit_lifetime_cv = test_implicit_lifetime<Val, T> //
&& test_implicit_lifetime<Val, const T> //
&& test_implicit_lifetime<Val, volatile T> //
&& test_implicit_lifetime<Val, const volatile T>;

// Scalar types, N5014 [basic.types.general]/9
static_assert(test_implicit_lifetime_cv<true, int>);
static_assert(test_implicit_lifetime_cv<true, UnscopedEnum>);
static_assert(test_implicit_lifetime_cv<true, ScopedEnum>);
static_assert(test_implicit_lifetime_cv<true, void*>);
static_assert(test_implicit_lifetime_cv<true, int*>);
static_assert(test_implicit_lifetime_cv<true, void (*)()>);
static_assert(test_implicit_lifetime_cv<true, int TrivialClass::*>);
static_assert(test_implicit_lifetime_cv<true, int (TrivialClass::*)(int)>);
static_assert(test_implicit_lifetime_cv<true, nullptr_t>);

// 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<true, TrivialClass>);
static_assert(test_implicit_lifetime_cv<true, DefaultedDestructorClass>);
static_assert(test_implicit_lifetime_cv<true, DeletedDestructorClass>);
static_assert(test_implicit_lifetime_cv<false, UserProvidedDestructorClass>);
static_assert(test_implicit_lifetime_cv<true, StringAggregateWithImplicitlyDeclaredDestructor>);
static_assert(test_implicit_lifetime_cv<false, StringAggregateWithUserProvidedDestructor>);
static_assert(test_implicit_lifetime_cv<true, NonAggregateWithTrivialCtorAndTrivialDtor>);
#ifndef __clang__ // TRANSITION, LLVM-160610
static_assert(test_implicit_lifetime_cv<false, NonAggregateWithNonTrivialCtor>);
static_assert(test_implicit_lifetime_cv<false, NonAggregateWithUserProvidedCtor>);
#endif // ^^^ no workaround ^^^
static_assert(test_implicit_lifetime_cv<false, NonAggregateWithDeletedDtor>);
static_assert(test_implicit_lifetime_cv<false, NonAggregateWithUserProvidedDtor>);

// Arrays
static_assert(test_implicit_lifetime_cv<true, int[]>);
static_assert(test_implicit_lifetime_cv<true, int[2]>);
static_assert(test_implicit_lifetime_cv<true, TrivialClass[]>);
static_assert(test_implicit_lifetime_cv<true, TrivialClass[10]>);
static_assert(test_implicit_lifetime_cv<true, UserProvidedDestructorClass[]>);
static_assert(test_implicit_lifetime_cv<true, UserProvidedDestructorClass[12]>);
static_assert(test_implicit_lifetime_cv<true, IncompleteClass[]>);
static_assert(test_implicit_lifetime_cv<true, IncompleteClass[20]>);

static_assert(test_implicit_lifetime_cv<false, void>);
static_assert(test_implicit_lifetime<false, long&>);
static_assert(test_implicit_lifetime<false, long&&>);
static_assert(test_implicit_lifetime<false, const long&>);
static_assert(test_implicit_lifetime<false, const long&&>);
#endif // ^^^ defined(__cpp_lib_is_implicit_lifetime) ^^^
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down