[libc++] Implement format_error.
This is the first step at implementing <format>. It adds the <format> header
and implements the `format_error`. class.
Implemnts parts of:
-P0645 Text Formatting
Reviewed By: ldionne, #libc, miscco, curdeius
Differential Revision: https://reviews.llvm.org/D92214
GitOrigin-RevId: 081c1db02dd2b48cf736d44862f7d7e8c2869577
diff --git a/docs/Cxx2aStatusPaperStatus.csv b/docs/Cxx2aStatusPaperStatus.csv
index e30a289..b3b60d2 100644
--- a/docs/Cxx2aStatusPaperStatus.csv
+++ b/docs/Cxx2aStatusPaperStatus.csv
@@ -103,7 +103,7 @@
"`P0466 <https://wg21.link/P0466>`__","LWG","Layout-compatibility and Pointer-interconvertibility Traits","Cologne","",""
"`P0553 <https://wg21.link/P0553>`__","LWG","Bit operations","Cologne","|Complete|","9.0"
"`P0631 <https://wg21.link/P0631>`__","LWG","Math Constants","Cologne","|Complete|","11.0"
-"`P0645 <https://wg21.link/P0645>`__","LWG","Text Formatting","Cologne","",""
+"`P0645 <https://wg21.link/P0645>`__","LWG","Text Formatting","Cologne","|In Progress|",""
"`P0660 <https://wg21.link/P0660>`__","LWG","Stop Token and Joining Thread, Rev 10","Cologne","",""
"`P0784 <https://wg21.link/P0784>`__","CWG","More constexpr containers","Cologne","|Complete|","12.0"
"`P0980 <https://wg21.link/P0980>`__","LWG","Making std::string constexpr","Cologne","",""
diff --git a/docs/FeatureTestMacroTable.rst b/docs/FeatureTestMacroTable.rst
index ed05488..5fe7005 100644
--- a/docs/FeatureTestMacroTable.rst
+++ b/docs/FeatureTestMacroTable.rst
@@ -234,6 +234,8 @@
------------------------------------------------- -----------------
``__cpp_lib_execution`` *unimplemented*
------------------------------------------------- -----------------
+ ``__cpp_lib_format`` *unimplemented*
+ ------------------------------------------------- -----------------
``__cpp_lib_generic_unordered_lookup`` ``201811L``
------------------------------------------------- -----------------
``__cpp_lib_int_pow2`` ``202002L``
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 77e5e55..9226d98 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -99,6 +99,7 @@
fenv.h
filesystem
float.h
+ format
forward_list
fstream
functional
diff --git a/include/format b/include/format
new file mode 100644
index 0000000..833423a
--- /dev/null
+++ b/include/format
@@ -0,0 +1,56 @@
+// -*- C++ -*-
+//===--------------------------- format -----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_FORMAT
+#define _LIBCPP_FORMAT
+
+/*
+
+namespace std {
+ // [format.error], class format_error
+ class format_error : public runtime_error {
+ public:
+ explicit format_error(const string& what_arg);
+ explicit format_error(const char* what_arg);
+ };
+}
+
+*/
+
+#include <__config>
+#include <stdexcept>
+#include <version>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 17
+
+class _LIBCPP_EXCEPTION_ABI format_error : public runtime_error {
+public:
+ _LIBCPP_INLINE_VISIBILITY explicit format_error(const string& __s)
+ : runtime_error(__s) {}
+ _LIBCPP_INLINE_VISIBILITY explicit format_error(const char* __s)
+ : runtime_error(__s) {}
+ virtual ~format_error() noexcept;
+};
+
+#endif //_LIBCPP_STD_VER > 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP_FORMAT
diff --git a/include/module.modulemap b/include/module.modulemap
index 750cd38..56b49c4 100644
--- a/include/module.modulemap
+++ b/include/module.modulemap
@@ -292,6 +292,10 @@
header "filesystem"
export *
}
+ module format {
+ header "format"
+ export *
+ }
module forward_list {
header "forward_list"
export initializer_list
diff --git a/include/version b/include/version
index 813bc1a..77183e5 100644
--- a/include/version
+++ b/include/version
@@ -72,6 +72,7 @@
__cpp_lib_execution 201902L <execution>
201603L // C++17
__cpp_lib_filesystem 201703L <filesystem>
+__cpp_lib_format 201907L <format>
__cpp_lib_gcd_lcm 201606L <numeric>
__cpp_lib_generic_associative_lookup 201304L <map> <set>
__cpp_lib_generic_unordered_lookup 201811L <unordered_map> <unordered_set>
@@ -313,6 +314,7 @@
# define __cpp_lib_erase_if 202002L
# undef __cpp_lib_execution
// # define __cpp_lib_execution 201902L
+// # define __cpp_lib_format 201907L
# define __cpp_lib_generic_unordered_lookup 201811L
# define __cpp_lib_int_pow2 202002L
// # define __cpp_lib_integer_comparison_functions 202002L
diff --git a/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist b/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
index 8aea8bb..c472a3a 100644
--- a/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
+++ b/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
@@ -1039,6 +1039,9 @@
{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwED0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwED2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__112format_errorD0Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__112format_errorD1Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__112format_errorD2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__112future_errorC1ENS_10error_codeE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__112future_errorC2ENS_10error_codeE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__112future_errorD0Ev', 'type': 'FUNC'}
@@ -1985,6 +1988,7 @@
{'is_defined': True, 'name': '__ZTINSt3__112codecvt_baseE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTINSt3__112ctype_bynameIcEE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTINSt3__112ctype_bynameIwEE', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '__ZTINSt3__112format_errorE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTINSt3__112future_errorE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTINSt3__112strstreambufE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTINSt3__112system_errorE', 'size': 0, 'type': 'OBJECT'}
@@ -2193,6 +2197,7 @@
{'is_defined': True, 'name': '__ZTSNSt3__112codecvt_baseE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTSNSt3__112ctype_bynameIcEE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTSNSt3__112ctype_bynameIwEE', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '__ZTSNSt3__112format_errorE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTSNSt3__112future_errorE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTSNSt3__112strstreambufE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTSNSt3__112system_errorE', 'size': 0, 'type': 'OBJECT'}
@@ -2377,6 +2382,7 @@
{'is_defined': True, 'name': '__ZTVNSt3__112bad_weak_ptrE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTVNSt3__112ctype_bynameIcEE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTVNSt3__112ctype_bynameIwEE', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '__ZTVNSt3__112format_errorE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTVNSt3__112future_errorE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTVNSt3__112strstreambufE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZTVNSt3__112system_errorE', 'size': 0, 'type': 'OBJECT'}
diff --git a/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist b/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
index c7ad0f4..46e3ef7 100644
--- a/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
+++ b/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
@@ -726,6 +726,9 @@
{'is_defined': True, 'name': '_ZNSt3__112ctype_bynameIwED0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112ctype_bynameIwED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112ctype_bynameIwED2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__112format_errorD0Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__112format_errorD1Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__112format_errorD2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112future_errorC1ENS_10error_codeE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112future_errorC2ENS_10error_codeE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__112future_errorD0Ev', 'type': 'FUNC'}
@@ -1648,6 +1651,7 @@
{'is_defined': True, 'name': '_ZTINSt3__112codecvt_baseE', 'size': 16, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTINSt3__112ctype_bynameIcEE', 'size': 24, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTINSt3__112ctype_bynameIwEE', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTINSt3__112format_errorE', 'size': 24, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTINSt3__112future_errorE', 'size': 24, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTINSt3__112strstreambufE', 'size': 24, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTINSt3__112system_errorE', 'size': 24, 'type': 'OBJECT'}
@@ -1776,6 +1780,7 @@
{'is_defined': True, 'name': '_ZTSNSt3__112codecvt_baseE', 'size': 23, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTSNSt3__112ctype_bynameIcEE', 'size': 26, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTSNSt3__112ctype_bynameIwEE', 'size': 26, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSNSt3__112format_errorE', 'size': 23, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTSNSt3__112future_errorE', 'size': 23, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTSNSt3__112strstreambufE', 'size': 23, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTSNSt3__112system_errorE', 'size': 23, 'type': 'OBJECT'}
@@ -1908,6 +1913,7 @@
{'is_defined': True, 'name': '_ZTVNSt3__112bad_weak_ptrE', 'size': 40, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTVNSt3__112ctype_bynameIcEE', 'size': 104, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTVNSt3__112ctype_bynameIwEE', 'size': 136, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVNSt3__112format_errorE', 'size': 40, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTVNSt3__112future_errorE', 'size': 40, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTVNSt3__112strstreambufE', 'size': 128, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZTVNSt3__112system_errorE', 'size': 40, 'type': 'OBJECT'}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c482068..5beb81e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -12,6 +12,7 @@
condition_variable.cpp
condition_variable_destructor.cpp
exception.cpp
+ format.cpp
functional.cpp
future.cpp
hash.cpp
diff --git a/src/format.cpp b/src/format.cpp
new file mode 100644
index 0000000..8ae9554
--- /dev/null
+++ b/src/format.cpp
@@ -0,0 +1,15 @@
+//===------------------------- format.cpp ---------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "format"
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+format_error::~format_error() noexcept = default;
+
+_LIBCPP_END_NAMESPACE_STD
diff --git a/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp
index 5e6fa2b..84486ed 100644
--- a/test/libcxx/double_include.sh.cpp
+++ b/test/libcxx/double_include.sh.cpp
@@ -91,6 +91,7 @@
# include <filesystem>
#endif
#include <float.h>
+#include <format>
#include <forward_list>
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
# include <fstream>
diff --git a/test/libcxx/min_max_macros.compile.pass.cpp b/test/libcxx/min_max_macros.compile.pass.cpp
index 6bf58c7..3e75de5 100644
--- a/test/libcxx/min_max_macros.compile.pass.cpp
+++ b/test/libcxx/min_max_macros.compile.pass.cpp
@@ -136,6 +136,8 @@
#endif
#include <float.h>
TEST_MACROS();
+#include <format>
+TEST_MACROS();
#include <forward_list>
TEST_MACROS();
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
diff --git a/test/libcxx/no_assert_include.compile.pass.cpp b/test/libcxx/no_assert_include.compile.pass.cpp
index 287039b..221c39a 100644
--- a/test/libcxx/no_assert_include.compile.pass.cpp
+++ b/test/libcxx/no_assert_include.compile.pass.cpp
@@ -84,6 +84,7 @@
# include <filesystem>
#endif
#include <float.h>
+#include <format>
#include <forward_list>
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
# include <fstream>
diff --git a/test/std/language.support/support.limits/support.limits.general/format.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/format.version.pass.cpp
new file mode 100644
index 0000000..21707a5
--- /dev/null
+++ b/test/std/language.support/support.limits/support.limits.general/format.version.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+//
+// clang-format off
+
+// <format>
+
+// Test the feature test macros defined by <format>
+
+/* Constant Value
+ __cpp_lib_format 201907L [C++20]
+*/
+
+#include <format>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 14
+
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_format
+# error "__cpp_lib_format should be defined in c++20"
+# endif
+# if __cpp_lib_format != 201907L
+# error "__cpp_lib_format should have the value 201907L in c++20"
+# endif
+# else // _LIBCPP_VERSION
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#elif TEST_STD_VER > 20
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_format
+# error "__cpp_lib_format should be defined in c++2b"
+# endif
+# if __cpp_lib_format != 201907L
+# error "__cpp_lib_format should have the value 201907L in c++2b"
+# endif
+# else // _LIBCPP_VERSION
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#endif // TEST_STD_VER > 20
+
+int main(int, char**) { return 0; }
diff --git a/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
index 9e96e2e..2fe0dfc 100644
--- a/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
+++ b/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
@@ -67,6 +67,7 @@
__cpp_lib_execution 201603L [C++17]
201902L [C++20]
__cpp_lib_filesystem 201703L [C++17]
+ __cpp_lib_format 201907L [C++20]
__cpp_lib_gcd_lcm 201606L [C++17]
__cpp_lib_generic_associative_lookup 201304L [C++14]
__cpp_lib_generic_unordered_lookup 201811L [C++20]
@@ -353,6 +354,10 @@
# error "__cpp_lib_filesystem should not be defined before c++17"
# endif
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined before c++20"
+# endif
+
# ifdef __cpp_lib_gcd_lcm
# error "__cpp_lib_gcd_lcm should not be defined before c++17"
# endif
@@ -884,6 +889,10 @@
# error "__cpp_lib_filesystem should not be defined before c++17"
# endif
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined before c++20"
+# endif
+
# ifdef __cpp_lib_gcd_lcm
# error "__cpp_lib_gcd_lcm should not be defined before c++17"
# endif
@@ -1541,6 +1550,10 @@
# error "__cpp_lib_filesystem should have the value 201703L in c++17"
# endif
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined before c++20"
+# endif
+
# ifndef __cpp_lib_gcd_lcm
# error "__cpp_lib_gcd_lcm should be defined in c++17"
# endif
@@ -2582,6 +2595,19 @@
# error "__cpp_lib_filesystem should have the value 201703L in c++20"
# endif
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_format
+# error "__cpp_lib_format should be defined in c++20"
+# endif
+# if __cpp_lib_format != 201907L
+# error "__cpp_lib_format should have the value 201907L in c++20"
+# endif
+# else // _LIBCPP_VERSION
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
# ifndef __cpp_lib_gcd_lcm
# error "__cpp_lib_gcd_lcm should be defined in c++20"
# endif
@@ -3788,6 +3814,19 @@
# error "__cpp_lib_filesystem should have the value 201703L in c++2b"
# endif
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_format
+# error "__cpp_lib_format should be defined in c++2b"
+# endif
+# if __cpp_lib_format != 201907L
+# error "__cpp_lib_format should have the value 201907L in c++2b"
+# endif
+# else // _LIBCPP_VERSION
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
# ifndef __cpp_lib_gcd_lcm
# error "__cpp_lib_gcd_lcm should be defined in c++2b"
# endif
diff --git a/test/std/utilities/format/format.error/format.error.pass.cpp b/test/std/utilities/format/format.error/format.error.pass.cpp
new file mode 100644
index 0000000..ea28ee9
--- /dev/null
+++ b/test/std/utilities/format/format.error/format.error.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// This test requires the dylib support introduced in D92214.
+// XFAIL: with_system_cxx_lib=macosx10.15
+// XFAIL: with_system_cxx_lib=macosx10.14
+// XFAIL: with_system_cxx_lib=macosx10.13
+// XFAIL: with_system_cxx_lib=macosx10.12
+// XFAIL: with_system_cxx_lib=macosx10.11
+// XFAIL: with_system_cxx_lib=macosx10.10
+// XFAIL: with_system_cxx_lib=macosx10.9
+
+// <format>
+
+// class format_error;
+
+#include <format>
+#include <type_traits>
+#include <cstring>
+#include <string>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+ static_assert(std::is_base_of_v<std::runtime_error, std::format_error>);
+ static_assert(std::is_polymorphic_v<std::format_error>);
+
+ {
+ const char* msg = "format_error message c-string";
+ std::format_error e(msg);
+ assert(std::strcmp(e.what(), msg) == 0);
+ std::format_error e2(e);
+ assert(std::strcmp(e2.what(), msg) == 0);
+ e2 = e;
+ assert(std::strcmp(e2.what(), msg) == 0);
+ }
+ {
+ std::string msg("format_error message std::string");
+ std::format_error e(msg);
+ assert(e.what() == msg);
+ std::format_error e2(e);
+ assert(e2.what() == msg);
+ e2 = e;
+ assert(e2.what() == msg);
+ }
+
+ return 0;
+}
diff --git a/test/std/utilities/format/version.compile.pass.cpp b/test/std/utilities/format/version.compile.pass.cpp
new file mode 100644
index 0000000..e61f58f
--- /dev/null
+++ b/test/std/utilities/format/version.compile.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <format>
+
+#include <format>
+
+#include "test_macros.h"
+
+#ifndef _LIBCPP_VERSION
+# error _LIBCPP_VERSION not defined
+#endif
+
+// Required for MSVC internal test runner compatibility.
+int main(int, char**) { return 0; }
diff --git a/utils/generate_feature_test_macro_components.py b/utils/generate_feature_test_macro_components.py
index 00de15d..6abc132 100755
--- a/utils/generate_feature_test_macro_components.py
+++ b/utils/generate_feature_test_macro_components.py
@@ -271,6 +271,11 @@
"values": { "c++17": 201703 },
"headers": ["filesystem"],
}, {
+ "name": "__cpp_lib_format",
+ "values": { "c++20": 201907 },
+ "headers": ["format"],
+ "unimplemented": True,
+ }, {
"name": "__cpp_lib_gcd_lcm",
"values": { "c++17": 201606 },
"headers": ["numeric"],