[libcxx-commits] [libcxx] 16a1c85 - [libc++] Implement P1328R1 constexpr std::type_info::operator==

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Feb 7 17:03:59 PST 2023


Author: Louis Dionne
Date: 2023-02-07T17:03:45-08:00
New Revision: 16a1c851713a5825daed8ea4a887078a63488562

URL: https://github.com/llvm/llvm-project/commit/16a1c851713a5825daed8ea4a887078a63488562
DIFF: https://github.com/llvm/llvm-project/commit/16a1c851713a5825daed8ea4a887078a63488562.diff

LOG: [libc++] Implement P1328R1 constexpr std::type_info::operator==

Differential Revision: https://reviews.llvm.org/D143447

Added: 
    libcxx/test/std/language.support/support.rtti/type.info/type_info.equal.pass.cpp

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/docs/ReleaseNotes.rst
    libcxx/docs/Status/Cxx2bPapers.csv
    libcxx/include/typeinfo
    libcxx/include/version
    libcxx/test/std/language.support/support.limits/support.limits.general/typeinfo.version.compile.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index b46fc8c0c4baa..df4dfc4a9a12a 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -316,7 +316,7 @@ Status
     ------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_memory``                    ``202202L``
     ------------------------------------------------- -----------------
-    ``__cpp_lib_constexpr_typeinfo``                  *unimplemented*
+    ``__cpp_lib_constexpr_typeinfo``                  ``202106L``
     ------------------------------------------------- -----------------
     ``__cpp_lib_expected``                            ``202202L``
     ------------------------------------------------- -----------------

diff  --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index 8a04afb1a1459..20b2b09cdaf60 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -38,6 +38,8 @@ What's New in Libc++ 17.0.0?
 Implemented Papers
 ------------------
 
+- P1328R1 - `constexpr type_info::operator==()`
+
 Improvements and New Features
 -----------------------------
 

diff  --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv
index e3f39d4250547..626f6cd9bb107 100644
--- a/libcxx/docs/Status/Cxx2bPapers.csv
+++ b/libcxx/docs/Status/Cxx2bPapers.csv
@@ -14,7 +14,7 @@
 "`P0401R6 <https://wg21.link/P0401R6>`__","LWG","Providing size feedback in the Allocator interface","June 2021","|Complete|","15.0"
 "`P0448R4 <https://wg21.link/P0448R4>`__","LWG","A strstream replacement using span<charT> as buffer","June 2021","",""
 "`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","",""
-"`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","",""
+"`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","|Complete|","17.0"
 "`P1425R4 <https://wg21.link/P1425R4>`__","LWG","Iterators pair constructors for stack and queue","June 2021","|Complete|","14.0","|ranges|"
 "`P1518R2 <https://wg21.link/P1518R2>`__","LWG","Stop overconstraining allocators in container deduction guides","June 2021","|Complete|","13.0"
 "`P1659R3 <https://wg21.link/P1659R3>`__","LWG","starts_with and ends_with","June 2021","","","|ranges|"

diff  --git a/libcxx/include/typeinfo b/libcxx/include/typeinfo
index 443103939849a..5627da16cbc0c 100644
--- a/libcxx/include/typeinfo
+++ b/libcxx/include/typeinfo
@@ -21,7 +21,7 @@ class type_info
 public:
     virtual ~type_info();
 
-    bool operator==(const type_info& rhs) const noexcept;
+    bool operator==(const type_info& rhs) const noexcept; // constexpr since C++23
     bool operator!=(const type_info& rhs) const noexcept; // removed in C++20
 
     bool before(const type_info& rhs) const noexcept;
@@ -59,6 +59,7 @@ public:
 #include <__assert> // all public C++ headers provide the assertion handler
 #include <__availability>
 #include <__config>
+#include <__type_traits/is_constant_evaluated.h>
 #include <cstddef>
 #include <cstdint>
 #include <cstdlib>
@@ -104,8 +105,13 @@ public:
 
     size_t hash_code() const _NOEXCEPT;
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23
     bool operator==(const type_info& __arg) const _NOEXCEPT {
+      // When evaluated in a constant expression, both type infos simply can't come
+      // from 
diff erent translation units, so it is sufficient to compare their addresses.
+      if (__libcpp_is_constant_evaluated()) {
+        return this == &__arg;
+      }
       return __compare(__arg) == 0;
     }
 
@@ -330,9 +336,14 @@ public:
       return __impl::__hash(__type_name);
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23
     bool operator==(const type_info& __arg) const _NOEXCEPT
     {
+      // When evaluated in a constant expression, both type infos simply can't come
+      // from 
diff erent translation units, so it is sufficient to compare their addresses.
+      if (__libcpp_is_constant_evaluated()) {
+        return this == &__arg;
+      }
       return __impl::__eq(__type_name, __arg.__type_name);
     }
 

diff  --git a/libcxx/include/version b/libcxx/include/version
index 9705229a1c522..44a081a688303 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -392,7 +392,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 // # define __cpp_lib_constexpr_cmath                      202202L
 # undef  __cpp_lib_constexpr_memory
 # define __cpp_lib_constexpr_memory                     202202L
-// # define __cpp_lib_constexpr_typeinfo                   202106L
+# define __cpp_lib_constexpr_typeinfo                   202106L
 # define __cpp_lib_expected                             202202L
 # define __cpp_lib_forward_like                         202207L
 // # define __cpp_lib_invoke_r                             202106L

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/typeinfo.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/typeinfo.version.compile.pass.cpp
index 75abf3e8fc9c0..3cb2502d0af69 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/typeinfo.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/typeinfo.version.compile.pass.cpp
@@ -48,17 +48,11 @@
 
 #elif TEST_STD_VER > 20
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_constexpr_typeinfo
-#     error "__cpp_lib_constexpr_typeinfo should be defined in c++2b"
-#   endif
-#   if __cpp_lib_constexpr_typeinfo != 202106L
-#     error "__cpp_lib_constexpr_typeinfo should have the value 202106L in c++2b"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_constexpr_typeinfo
-#     error "__cpp_lib_constexpr_typeinfo should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_constexpr_typeinfo
+#   error "__cpp_lib_constexpr_typeinfo should be defined in c++2b"
+# endif
+# if __cpp_lib_constexpr_typeinfo != 202106L
+#   error "__cpp_lib_constexpr_typeinfo should have the value 202106L in c++2b"
 # endif
 
 #endif // TEST_STD_VER > 20

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 9c1816bbce518..b02679d734ae7 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -3988,17 +3988,11 @@
 #   error "__cpp_lib_constexpr_tuple should have the value 201811L in c++2b"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_constexpr_typeinfo
-#     error "__cpp_lib_constexpr_typeinfo should be defined in c++2b"
-#   endif
-#   if __cpp_lib_constexpr_typeinfo != 202106L
-#     error "__cpp_lib_constexpr_typeinfo should have the value 202106L in c++2b"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_constexpr_typeinfo
-#     error "__cpp_lib_constexpr_typeinfo should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_constexpr_typeinfo
+#   error "__cpp_lib_constexpr_typeinfo should be defined in c++2b"
+# endif
+# if __cpp_lib_constexpr_typeinfo != 202106L
+#   error "__cpp_lib_constexpr_typeinfo should have the value 202106L in c++2b"
 # endif
 
 # ifndef __cpp_lib_constexpr_utility

diff  --git a/libcxx/test/std/language.support/support.rtti/type.info/type_info.equal.pass.cpp b/libcxx/test/std/language.support/support.rtti/type.info/type_info.equal.pass.cpp
new file mode 100644
index 0000000000000..3f5dd96261923
--- /dev/null
+++ b/libcxx/test/std/language.support/support.rtti/type.info/type_info.equal.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// class type_info
+//
+//  bool operator==(const type_info& rhs) const noexcept; // constexpr since C++23
+
+// UNSUPPORTED: no-rtti
+
+// When we build for Windows on top of the VC runtime, `typeinfo::operator==` may not
+// be `constexpr` (depending on the version of the VC runtime). So this test can fail.
+// UNSUPPORTED: target={{.+}}-windows-msvc && !libcpp-no-vcruntime
+
+#include <typeinfo>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Base {
+  virtual void func() {}
+};
+struct Derived : Base {
+  virtual void func() {}
+};
+
+TEST_CONSTEXPR_CXX23 bool test() {
+  // Test when storing typeid() in a const ref
+  {
+    std::type_info const& t1 = typeid(int);
+    std::type_info const& t2 = typeid(long);
+    assert(t1 == t1);
+    assert(t2 == t2);
+    assert(t1 != t2);
+  }
+
+  // Test when using `typeid()` directly
+  {
+    struct Foo { };
+    struct Bar { };
+    assert(typeid(Foo) == typeid(Foo));
+    assert(typeid(Foo) != typeid(Bar));
+  }
+
+  // Test when using typeid(object) instead of typeid(type)
+  {
+    int x = 0, y = 0;
+    long z = 0;
+    assert(typeid(x) == typeid(y));
+    assert(typeid(x) != typeid(z));
+  }
+
+  // Check with derived/base types
+  {
+    Derived derived;
+    Base const& as_base = derived;
+    assert(typeid(as_base) == typeid(Derived));
+  }
+
+  // Check noexcept-ness
+  {
+    std::type_info const& t1 = typeid(int); (void)t1;
+    std::type_info const& t2 = typeid(long); (void)t2;
+    ASSERT_NOEXCEPT(t1 == t2);
+  }
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 23
+  static_assert(test());
+#endif
+  return 0;
+}

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 69cb94272de87..4cf52fb88bbf1 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -267,7 +267,6 @@ def add_version_header(tc):
     "name": "__cpp_lib_constexpr_typeinfo",
     "values": { "c++2b": 202106 },
     "headers": ["typeinfo"],
-    "unimplemented": True,
   }, {
     "name": "__cpp_lib_constexpr_utility",
     "values": { "c++20": 201811 },


        


More information about the libcxx-commits mailing list