Skip to content

Commit 16a1c85

Browse files
committed
[libc++] Implement P1328R1 constexpr std::type_info::operator==
Differential Revision: https://reviews.llvm.org/D143447
1 parent 8fdc3ff commit 16a1c85

File tree

9 files changed

+108
-29
lines changed

9 files changed

+108
-29
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ Status
316316
------------------------------------------------- -----------------
317317
``__cpp_lib_constexpr_memory`` ``202202L``
318318
------------------------------------------------- -----------------
319-
``__cpp_lib_constexpr_typeinfo`` *unimplemented*
319+
``__cpp_lib_constexpr_typeinfo`` ``202106L``
320320
------------------------------------------------- -----------------
321321
``__cpp_lib_expected`` ``202202L``
322322
------------------------------------------------- -----------------

libcxx/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ What's New in Libc++ 17.0.0?
3838
Implemented Papers
3939
------------------
4040

41+
- P1328R1 - `constexpr type_info::operator==()`
42+
4143
Improvements and New Features
4244
-----------------------------
4345

libcxx/docs/Status/Cxx2bPapers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"`P0401R6 <https://wg21.link/P0401R6>`__","LWG","Providing size feedback in the Allocator interface","June 2021","|Complete|","15.0"
1515
"`P0448R4 <https://wg21.link/P0448R4>`__","LWG","A strstream replacement using span<charT> as buffer","June 2021","",""
1616
"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","",""
17-
"`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","",""
17+
"`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","|Complete|","17.0"
1818
"`P1425R4 <https://wg21.link/P1425R4>`__","LWG","Iterators pair constructors for stack and queue","June 2021","|Complete|","14.0","|ranges|"
1919
"`P1518R2 <https://wg21.link/P1518R2>`__","LWG","Stop overconstraining allocators in container deduction guides","June 2021","|Complete|","13.0"
2020
"`P1659R3 <https://wg21.link/P1659R3>`__","LWG","starts_with and ends_with","June 2021","","","|ranges|"

libcxx/include/typeinfo

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class type_info
2121
public:
2222
virtual ~type_info();
2323
24-
bool operator==(const type_info& rhs) const noexcept;
24+
bool operator==(const type_info& rhs) const noexcept; // constexpr since C++23
2525
bool operator!=(const type_info& rhs) const noexcept; // removed in C++20
2626
2727
bool before(const type_info& rhs) const noexcept;
@@ -59,6 +59,7 @@ public:
5959
#include <__assert> // all public C++ headers provide the assertion handler
6060
#include <__availability>
6161
#include <__config>
62+
#include <__type_traits/is_constant_evaluated.h>
6263
#include <cstddef>
6364
#include <cstdint>
6465
#include <cstdlib>
@@ -104,8 +105,13 @@ public:
104105

105106
size_t hash_code() const _NOEXCEPT;
106107

107-
_LIBCPP_INLINE_VISIBILITY
108+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23
108109
bool operator==(const type_info& __arg) const _NOEXCEPT {
110+
// When evaluated in a constant expression, both type infos simply can't come
111+
// from different translation units, so it is sufficient to compare their addresses.
112+
if (__libcpp_is_constant_evaluated()) {
113+
return this == &__arg;
114+
}
109115
return __compare(__arg) == 0;
110116
}
111117

@@ -330,9 +336,14 @@ public:
330336
return __impl::__hash(__type_name);
331337
}
332338

333-
_LIBCPP_INLINE_VISIBILITY
339+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23
334340
bool operator==(const type_info& __arg) const _NOEXCEPT
335341
{
342+
// When evaluated in a constant expression, both type infos simply can't come
343+
// from different translation units, so it is sufficient to compare their addresses.
344+
if (__libcpp_is_constant_evaluated()) {
345+
return this == &__arg;
346+
}
336347
return __impl::__eq(__type_name, __arg.__type_name);
337348
}
338349

libcxx/include/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ __cpp_lib_void_t 201411L <type_traits>
392392
// # define __cpp_lib_constexpr_cmath 202202L
393393
# undef __cpp_lib_constexpr_memory
394394
# define __cpp_lib_constexpr_memory 202202L
395-
// # define __cpp_lib_constexpr_typeinfo 202106L
395+
# define __cpp_lib_constexpr_typeinfo 202106L
396396
# define __cpp_lib_expected 202202L
397397
# define __cpp_lib_forward_like 202207L
398398
// # define __cpp_lib_invoke_r 202106L

libcxx/test/std/language.support/support.limits/support.limits.general/typeinfo.version.compile.pass.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,11 @@
4848

4949
#elif TEST_STD_VER > 20
5050

51-
# if !defined(_LIBCPP_VERSION)
52-
# ifndef __cpp_lib_constexpr_typeinfo
53-
# error "__cpp_lib_constexpr_typeinfo should be defined in c++2b"
54-
# endif
55-
# if __cpp_lib_constexpr_typeinfo != 202106L
56-
# error "__cpp_lib_constexpr_typeinfo should have the value 202106L in c++2b"
57-
# endif
58-
# else // _LIBCPP_VERSION
59-
# ifdef __cpp_lib_constexpr_typeinfo
60-
# error "__cpp_lib_constexpr_typeinfo should not be defined because it is unimplemented in libc++!"
61-
# endif
51+
# ifndef __cpp_lib_constexpr_typeinfo
52+
# error "__cpp_lib_constexpr_typeinfo should be defined in c++2b"
53+
# endif
54+
# if __cpp_lib_constexpr_typeinfo != 202106L
55+
# error "__cpp_lib_constexpr_typeinfo should have the value 202106L in c++2b"
6256
# endif
6357

6458
#endif // TEST_STD_VER > 20

libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3988,17 +3988,11 @@
39883988
# error "__cpp_lib_constexpr_tuple should have the value 201811L in c++2b"
39893989
# endif
39903990

3991-
# if !defined(_LIBCPP_VERSION)
3992-
# ifndef __cpp_lib_constexpr_typeinfo
3993-
# error "__cpp_lib_constexpr_typeinfo should be defined in c++2b"
3994-
# endif
3995-
# if __cpp_lib_constexpr_typeinfo != 202106L
3996-
# error "__cpp_lib_constexpr_typeinfo should have the value 202106L in c++2b"
3997-
# endif
3998-
# else // _LIBCPP_VERSION
3999-
# ifdef __cpp_lib_constexpr_typeinfo
4000-
# error "__cpp_lib_constexpr_typeinfo should not be defined because it is unimplemented in libc++!"
4001-
# endif
3991+
# ifndef __cpp_lib_constexpr_typeinfo
3992+
# error "__cpp_lib_constexpr_typeinfo should be defined in c++2b"
3993+
# endif
3994+
# if __cpp_lib_constexpr_typeinfo != 202106L
3995+
# error "__cpp_lib_constexpr_typeinfo should have the value 202106L in c++2b"
40023996
# endif
40033997

40043998
# ifndef __cpp_lib_constexpr_utility
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// class type_info
10+
//
11+
// bool operator==(const type_info& rhs) const noexcept; // constexpr since C++23
12+
13+
// UNSUPPORTED: no-rtti
14+
15+
// When we build for Windows on top of the VC runtime, `typeinfo::operator==` may not
16+
// be `constexpr` (depending on the version of the VC runtime). So this test can fail.
17+
// UNSUPPORTED: target={{.+}}-windows-msvc && !libcpp-no-vcruntime
18+
19+
#include <typeinfo>
20+
#include <cassert>
21+
22+
#include "test_macros.h"
23+
24+
struct Base {
25+
virtual void func() {}
26+
};
27+
struct Derived : Base {
28+
virtual void func() {}
29+
};
30+
31+
TEST_CONSTEXPR_CXX23 bool test() {
32+
// Test when storing typeid() in a const ref
33+
{
34+
std::type_info const& t1 = typeid(int);
35+
std::type_info const& t2 = typeid(long);
36+
assert(t1 == t1);
37+
assert(t2 == t2);
38+
assert(t1 != t2);
39+
}
40+
41+
// Test when using `typeid()` directly
42+
{
43+
struct Foo { };
44+
struct Bar { };
45+
assert(typeid(Foo) == typeid(Foo));
46+
assert(typeid(Foo) != typeid(Bar));
47+
}
48+
49+
// Test when using typeid(object) instead of typeid(type)
50+
{
51+
int x = 0, y = 0;
52+
long z = 0;
53+
assert(typeid(x) == typeid(y));
54+
assert(typeid(x) != typeid(z));
55+
}
56+
57+
// Check with derived/base types
58+
{
59+
Derived derived;
60+
Base const& as_base = derived;
61+
assert(typeid(as_base) == typeid(Derived));
62+
}
63+
64+
// Check noexcept-ness
65+
{
66+
std::type_info const& t1 = typeid(int); (void)t1;
67+
std::type_info const& t2 = typeid(long); (void)t2;
68+
ASSERT_NOEXCEPT(t1 == t2);
69+
}
70+
return true;
71+
}
72+
73+
int main(int, char**) {
74+
test();
75+
#if TEST_STD_VER >= 23
76+
static_assert(test());
77+
#endif
78+
return 0;
79+
}

libcxx/utils/generate_feature_test_macro_components.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,6 @@ def add_version_header(tc):
267267
"name": "__cpp_lib_constexpr_typeinfo",
268268
"values": { "c++2b": 202106 },
269269
"headers": ["typeinfo"],
270-
"unimplemented": True,
271270
}, {
272271
"name": "__cpp_lib_constexpr_utility",
273272
"values": { "c++20": 201811 },

0 commit comments

Comments
 (0)