Skip to content

Commit c12730b

Browse files
committed
Address comments
1 parent 7d50c7b commit c12730b

File tree

3 files changed

+98
-76
lines changed

3 files changed

+98
-76
lines changed

libcxx/include/__type_traits/is_within_lifetime.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2020

2121
#if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_is_within_lifetime)
2222
template <class _Tp>
23-
_LIBCPP_HIDE_FROM_ABI inline consteval bool is_within_lifetime(const _Tp* __p) noexcept {
23+
_LIBCPP_HIDE_FROM_ABI consteval bool is_within_lifetime(const _Tp* __p) noexcept {
2424
if constexpr (is_function_v<_Tp>) {
2525
// Avoid multiple diagnostics
2626
static_assert(!is_function_v<_Tp>, "std::is_within_lifetime<T> cannot explicitly specify T as a function type");
27-
return true;
27+
return false;
2828
} else {
2929
return __builtin_is_within_lifetime(__p);
3030
}

libcxx/test/libcxx/utilities/meta/is_within_lifetime.verify.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10+
// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-16
1011

1112
// <type_traits>
1213

@@ -15,18 +16,11 @@
1516
// explicitly specified, even if it isn't evaluated
1617

1718
#include <type_traits>
18-
#include <cassert>
1919

20-
#include "test_macros.h"
21-
22-
void fn();
23-
24-
int main(int, char**) {
25-
#ifdef __cpp_lib_is_within_lifetime
26-
constexpr bool _ = true ? false : std::is_within_lifetime<void()>(&fn);
27-
// expected-error@*:* {{static assertion failed due to requirement '!is_function_v<void ()>': std::is_within_lifetime<T> cannot explicitly specify T as a function type}}
28-
#else
29-
// expected-no-diagnostics
30-
#endif
31-
return 0;
20+
template <class T>
21+
consteval bool checked_is_within_lifetime(T* p) {
22+
return p ? std::is_within_lifetime<T>(p) : false;
3223
}
24+
static_assert(!checked_is_within_lifetime<int>(nullptr));
25+
static_assert(!checked_is_within_lifetime<void()>(nullptr));
26+
// expected-error@*:* {{static assertion failed due to requirement '!is_function_v<void ()>': std::is_within_lifetime<T> cannot explicitly specify T as a function type}}

libcxx/test/std/utilities/meta/meta.const.eval/is_within_lifetime.compile.pass.cpp

Lines changed: 88 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10+
// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-16
1011

1112
// <type_traits>
1213

@@ -18,24 +19,6 @@
1819

1920
#include "test_macros.h"
2021

21-
#ifndef __cpp_lib_is_within_lifetime
22-
23-
// Check that it doesn't exist if the feature test macro isn't defined (via ADL)
24-
template <class T>
25-
constexpr decltype(static_cast<void>(is_within_lifetime(std::declval<T>())), bool{}) is_within_lifetime_exists(int) {
26-
return true;
27-
}
28-
template <class T>
29-
constexpr bool is_within_lifetime_exists(long) {
30-
return false;
31-
}
32-
33-
static_assert(!is_within_lifetime_exists<const std::integral_constant<bool, false>*>(0), "");
34-
35-
#elif TEST_STD_VER < 26
36-
# error __cpp_lib_is_within_lifetime defined before C++26
37-
#else // defined(__cpp_lib_is_within_lifetime) && TEST_STD_VER >= 26
38-
3922
ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<int*>())), bool);
4023
ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<const int*>())), bool);
4124
ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<void*>())), bool);
@@ -58,53 +41,101 @@ static_assert(is_within_lifetime_exists<const void*>);
5841
static_assert(!is_within_lifetime_exists<int>); // Not a pointer
5942
static_assert(!is_within_lifetime_exists<decltype(nullptr)>); // Not a pointer
6043
static_assert(!is_within_lifetime_exists<void() const>); // Not a pointer
61-
static_assert(!is_within_lifetime_exists<int S::*>); // Doesn't accept pointer-to-member
62-
static_assert(!is_within_lifetime_exists<void (S::*)()>);
63-
static_assert(!is_within_lifetime_exists<void (*)()>); // Doesn't match `const T*`
64-
65-
constexpr int i = 0;
66-
static_assert(std::is_within_lifetime(&i));
67-
static_assert(std::is_within_lifetime(const_cast<int*>(&i)));
68-
static_assert(std::is_within_lifetime(static_cast<const void*>(&i)));
69-
static_assert(std::is_within_lifetime(static_cast<void*>(const_cast<int*>(&i))));
70-
static_assert(std::is_within_lifetime<const int>(&i));
71-
static_assert(std::is_within_lifetime<int>(const_cast<int*>(&i)));
72-
static_assert(std::is_within_lifetime<const void>(static_cast<const void*>(&i)));
73-
static_assert(std::is_within_lifetime<void>(static_cast<void*>(const_cast<int*>(&i))));
74-
75-
constexpr union {
76-
int active;
77-
int inactive;
78-
} u{.active = 1};
79-
static_assert(std::is_within_lifetime(&u.active) && !std::is_within_lifetime(&u.inactive));
44+
static_assert(!is_within_lifetime_exists<int S::*>); // Doesn't accept pointer-to-data-member
45+
static_assert(!is_within_lifetime_exists<void (S::*)()>); // Doesn't accept pointer-to-member-function
46+
static_assert(!is_within_lifetime_exists<void (*)()>); // Doesn't match `const T*`
8047

8148
consteval bool f() {
82-
union {
83-
int active;
84-
int inactive;
85-
};
86-
if (std::is_within_lifetime(&active) || std::is_within_lifetime(&inactive))
87-
return false;
88-
active = 1;
89-
if (!std::is_within_lifetime(&active) || std::is_within_lifetime(&inactive))
90-
return false;
91-
inactive = 1;
92-
if (std::is_within_lifetime(&active) || !std::is_within_lifetime(&inactive))
93-
return false;
94-
int j;
95-
S s;
96-
return std::is_within_lifetime(&j) && std::is_within_lifetime(&s);
49+
// Test that it works with global variables whose lifetime is in a
50+
// different constant expression
51+
{
52+
static constexpr int i = 0;
53+
static_assert(std::is_within_lifetime(&i));
54+
// (Even when cast to a different type)
55+
static_assert(std::is_within_lifetime(const_cast<int*>(&i)));
56+
static_assert(std::is_within_lifetime(static_cast<const void*>(&i)));
57+
static_assert(std::is_within_lifetime(static_cast<void*>(const_cast<int*>(&i))));
58+
static_assert(std::is_within_lifetime<const int>(&i));
59+
static_assert(std::is_within_lifetime<int>(const_cast<int*>(&i)));
60+
static_assert(std::is_within_lifetime<const void>(static_cast<const void*>(&i)));
61+
static_assert(std::is_within_lifetime<void>(static_cast<void*>(const_cast<int*>(&i))));
62+
}
63+
64+
{
65+
static constexpr union {
66+
int member1;
67+
int member2;
68+
} u{.member2 = 1};
69+
static_assert(!std::is_within_lifetime(&u.member1) && std::is_within_lifetime(&u.member2));
70+
}
71+
72+
// Test that it works for varibles inside the same constant expression
73+
{
74+
int i = 0;
75+
assert(std::is_within_lifetime(&i));
76+
// (Even when cast to a different type)
77+
assert(std::is_within_lifetime(const_cast<int*>(&i)));
78+
assert(std::is_within_lifetime(static_cast<const void*>(&i)));
79+
assert(std::is_within_lifetime(static_cast<void*>(const_cast<int*>(&i))));
80+
assert(std::is_within_lifetime<const int>(&i));
81+
assert(std::is_within_lifetime<int>(const_cast<int*>(&i)));
82+
assert(std::is_within_lifetime<const void>(static_cast<const void*>(&i)));
83+
assert(std::is_within_lifetime<void>(static_cast<void*>(const_cast<int*>(&i))));
84+
}
85+
// Anonymous union
86+
{
87+
union {
88+
int member1;
89+
int member2;
90+
};
91+
assert(!std::is_within_lifetime(&member1) && !std::is_within_lifetime(&member2));
92+
member1 = 1;
93+
assert(std::is_within_lifetime(&member1) && !std::is_within_lifetime(&member2));
94+
member2 = 1;
95+
assert(!std::is_within_lifetime(&member1) && std::is_within_lifetime(&member2));
96+
}
97+
// Variant members
98+
{
99+
struct X {
100+
union {
101+
int member1;
102+
int member2;
103+
};
104+
} x;
105+
assert(!std::is_within_lifetime(&x.member1) && !std::is_within_lifetime(&x.member2));
106+
x.member1 = 1;
107+
assert(std::is_within_lifetime(&x.member1) && !std::is_within_lifetime(&x.member2));
108+
x.member2 = 1;
109+
assert(!std::is_within_lifetime(&x.member1) && std::is_within_lifetime(&x.member2));
110+
}
111+
// Unions
112+
{
113+
union X {
114+
int member1;
115+
int member2;
116+
} x;
117+
assert(!std::is_within_lifetime(&x.member1) && !std::is_within_lifetime(&x.member2));
118+
x.member1 = 1;
119+
assert(std::is_within_lifetime(&x.member1) && !std::is_within_lifetime(&x.member2));
120+
x.member2 = 1;
121+
assert(!std::is_within_lifetime(&x.member1) && std::is_within_lifetime(&x.member2));
122+
}
123+
{
124+
S s; // uninitialised
125+
assert(std::is_within_lifetime(&s));
126+
}
127+
128+
return true;
97129
}
98130
static_assert(f());
99131

100-
# ifndef TEST_COMPILER_MSVC
101-
// MSVC doesn't support consteval propagation :(
132+
// Check that it is a consteval (and consteval-propagating) function
133+
// (i.e., taking the address of below will fail because it will be an immediate function)
102134
template <typename T>
103135
constexpr void does_escalate(T p) {
104136
std::is_within_lifetime(p);
105137
}
106-
107-
template <typename T, void(T) = does_escalate<T>>
138+
template <typename T, void (*)(T) = &does_escalate<T>>
108139
constexpr bool check_escalated(int) {
109140
return false;
110141
}
@@ -114,6 +145,3 @@ constexpr bool check_escalated(long) {
114145
}
115146
static_assert(check_escalated<int*>(0), "");
116147
static_assert(check_escalated<void*>(0), "");
117-
# endif // defined(TEST_COMPILER_MSVC)
118-
119-
#endif // defined(__cpp_lib_is_within_lifetime) && TEST_STD_VER >= 26

0 commit comments

Comments
 (0)