[libcxx-commits] [libcxx] [libcxxabi] [libc++] Introduce the notion of a minimum header version (PR #166074)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Nov 18 06:28:20 PST 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/166074
>From b7433a55b4bae0d72c8f022ae700395a85951af9 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sun, 2 Nov 2025 16:34:51 +0100
Subject: [PATCH] [libc++] Introduce the notion of a minimum header version
---
libcxx/CMakeLists.txt | 4 ++
libcxx/docs/ABIGuarantees.rst | 17 ---------
libcxx/include/__config | 10 -----
libcxx/include/__configuration/abi.h | 14 -------
libcxx/include/__configuration/availability.h | 7 ++++
libcxx/include/__ostream/basic_ostream.h | 16 ++++----
libcxx/include/istream | 22 +++++------
libcxx/include/streambuf | 38 +++++++++----------
libcxx/include/valarray | 4 +-
libcxx/src/any.cpp | 4 ++
libcxx/src/charconv.cpp | 4 +-
libcxx/src/condition_variable_destructor.cpp | 2 +-
libcxx/src/error_category.cpp | 4 +-
libcxx/src/memory.cpp | 3 +-
libcxx/src/mutex_destructor.cpp | 2 +-
libcxx/src/optional.cpp | 4 ++
libcxx/src/string.cpp | 15 +++-----
libcxx/src/valarray.cpp | 3 +-
libcxx/src/vector.cpp | 4 +-
libcxxabi/CMakeLists.txt | 4 ++
20 files changed, 81 insertions(+), 100 deletions(-)
diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index a119850cd808e..070e55e85d3f9 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -205,6 +205,9 @@ set(LIBCXX_ABI_NAMESPACE "__${LIBCXX_ABI_VERSION}" CACHE STRING "The inline ABI
if (NOT LIBCXX_ABI_NAMESPACE MATCHES "__.*")
message(FATAL_ERROR "LIBCXX_ABI_NAMESPACE must be a reserved identifier, got '${LIBCXX_ABI_NAMESPACE}'.")
endif()
+set(LIBCXX_AVAILABILITY_MINIMUM_HEADER_VERSION "1" CACHE STRING
+ "Minimum version of the libc++ headers that are allowed to be used by binaries linked against the libc++ library. This
+ version must correspond to the major version of an LLVM release.")
option(LIBCXX_ABI_FORCE_ITANIUM "Ignore auto-detection and force use of the Itanium ABI.")
option(LIBCXX_ABI_FORCE_MICROSOFT "Ignore auto-detection and force use of the Microsoft ABI.")
@@ -523,6 +526,7 @@ function(cxx_add_basic_build_flags target)
# Let the library headers know they are currently being used to build the
# library.
target_compile_definitions(${target} PRIVATE -D_LIBCPP_BUILDING_LIBRARY)
+ target_compile_definitions(${target} PRIVATE -D_LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION=${LIBCXX_AVAILABILITY_MINIMUM_HEADER_VERSION})
# Make sure the library can be build without transitive includes. This makes
# it easier to upgrade the library to a newer language standard without build
diff --git a/libcxx/docs/ABIGuarantees.rst b/libcxx/docs/ABIGuarantees.rst
index 4d4674c7756a4..fc3cf8b7dd0a3 100644
--- a/libcxx/docs/ABIGuarantees.rst
+++ b/libcxx/docs/ABIGuarantees.rst
@@ -114,23 +114,6 @@ hand, backwards compatibility is generally guaranteed.
There are multiple ABI flags that change the symbols exported from the built library:
-``_LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON``
--------------------------------------------------
-This removes ``__basic_string_common<true>::__throw_length_error()`` and
-``__basic_string_common<true>::__throw_out_of_range()``. These symbols have been used by ``basic_string`` in the past,
-but are not referenced from the headers anymore.
-
-``_LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON``
-------------------------------------------------
-This removes ``__vector_base_common<true>::__throw_length_error()`` and
-``__vector_base_common<true>::__throw_out_of_range()``. These symbols have been used by ``vector`` in the past, but are
-not referenced from the headers anymore.
-
-``_LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10``
-----------------------------------------------
-This removes ``__itoa::__u32toa()`` and ``__iota::__u64toa``. These symbols have been used by ``to_chars`` in the past,
-but are not referenced from the headers anymore.
-
``_LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION``
-------------------------------------------------------
This replaces the symbols that are exported for ``basic_string`` to avoid exporting functions which are likely to be
diff --git a/libcxx/include/__config b/libcxx/include/__config
index d079bf8b500b6..48917aae8726c 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -360,16 +360,6 @@ typedef __char32_t char32_t;
# endif
# define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
-# ifdef _LIBCPP_BUILDING_LIBRARY
-# if _LIBCPP_ABI_VERSION > 1
-# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI
-# else
-# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1
-# endif
-# else
-# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI
-# endif
-
// Clang modules take a significant compile time hit when pushing and popping diagnostics.
// Since all the headers are marked as system headers unless _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER is defined, we can
// simply disable this pushing and popping when _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER isn't defined.
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index 38b85c6ac70de..f088fd92f29c0 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -63,9 +63,6 @@
// These flags are documented in ABIGuarantees.rst
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
-# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
-# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
-# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI
# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI
# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION
@@ -85,17 +82,6 @@
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
#elif _LIBCPP_ABI_VERSION == 1
-# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
-// Enable compiling copies of now inline methods into the dylib to support
-// applications compiled against older libraries. This is unnecessary with
-// COFF dllexport semantics, since dllexport forces a non-inline definition
-// of inline functions to be emitted anyway. Our own non-inline copy would
-// conflict with the dllexport-emitted copy, so we disable it. For XCOFF,
-// the linker will take issue with the symbols in the shared object if the
-// weak inline methods get visibility (such as from -fvisibility-inlines-hidden),
-// so disable it.
-# define _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
-# endif
// Feature macros for disabling pre ABI v1 features. All of these options
// are deprecated.
# if defined(__FreeBSD__)
diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index 5433df872fa39..d0e42a897122f 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -326,4 +326,11 @@
# define _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION
#endif
+// Only define a bunch of symbols in the dylib if we target LLVM 7 headers or older
+# if defined(_LIBCPP_BUILDING_LIBRARY) && _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 8
+# define _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8
+# else
+# define _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 _LIBCPP_HIDE_FROM_ABI
+# endif
+
#endif // _LIBCPP___CONFIGURATION_AVAILABILITY_H
diff --git a/libcxx/include/__ostream/basic_ostream.h b/libcxx/include/__ostream/basic_ostream.h
index effeef491f341..ac8bb1a3159f9 100644
--- a/libcxx/include/__ostream/basic_ostream.h
+++ b/libcxx/include/__ostream/basic_ostream.h
@@ -53,7 +53,7 @@ class basic_ostream : virtual public basic_ios<_CharT, _Traits> {
typedef typename traits_type::off_type off_type;
// 27.7.2.2 Constructor/destructor:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 explicit basic_ostream(basic_streambuf<char_type, traits_type>* __sb) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 explicit basic_ostream(basic_streambuf<char_type, traits_type>* __sb) {
this->init(__sb);
}
~basic_ostream() override;
@@ -67,7 +67,7 @@ class basic_ostream : virtual public basic_ios<_CharT, _Traits> {
// 27.7.2.3 Assign/swap
inline _LIBCPP_HIDE_FROM_ABI basic_ostream& operator=(basic_ostream&& __rhs);
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void swap(basic_ostream& __rhs) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void swap(basic_ostream& __rhs) {
basic_ios<char_type, traits_type>::swap(__rhs);
}
@@ -76,17 +76,17 @@ class basic_ostream : virtual public basic_ios<_CharT, _Traits> {
class sentry;
// 27.7.2.6 Formatted output:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& operator<<(basic_ostream& (*__pf)(basic_ostream&)) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_ostream& operator<<(basic_ostream& (*__pf)(basic_ostream&)) {
return __pf(*this);
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream&
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_ostream&
operator<<(basic_ios<char_type, traits_type>& (*__pf)(basic_ios<char_type, traits_type>&)) {
__pf(*this);
return *this;
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& operator<<(ios_base& (*__pf)(ios_base&)) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_ostream& operator<<(ios_base& (*__pf)(ios_base&)) {
__pf(*this);
return *this;
}
@@ -174,9 +174,9 @@ class basic_ostream : virtual public basic_ios<_CharT, _Traits> {
basic_ostream& flush();
// 27.7.2.5 seeks:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 pos_type tellp();
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& seekp(pos_type __pos);
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& seekp(off_type __off, ios_base::seekdir __dir);
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 pos_type tellp();
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_ostream& seekp(pos_type __pos);
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_ostream& seekp(off_type __off, ios_base::seekdir __dir);
protected:
_LIBCPP_HIDE_FROM_ABI basic_ostream() {} // extension, intentially does not initialize
diff --git a/libcxx/include/istream b/libcxx/include/istream
index 7f15521f91a8a..4fc4c6b133552 100644
--- a/libcxx/include/istream
+++ b/libcxx/include/istream
@@ -209,7 +209,7 @@ public:
typedef typename traits_type::off_type off_type;
// 27.7.1.1.1 Constructor/destructor:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 explicit basic_istream(basic_streambuf<char_type, traits_type>* __sb)
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 explicit basic_istream(basic_streambuf<char_type, traits_type>* __sb)
: __gc_(0) {
this->init(__sb);
}
@@ -221,7 +221,7 @@ protected:
// 27.7.1.1.2 Assign/swap:
inline _LIBCPP_HIDE_FROM_ABI basic_istream& operator=(basic_istream&& __rhs);
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void swap(basic_istream& __rhs) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void swap(basic_istream& __rhs) {
std::swap(__gc_, __rhs.__gc_);
basic_ios<char_type, traits_type>::swap(__rhs);
}
@@ -234,17 +234,17 @@ public:
class sentry;
// 27.7.1.2 Formatted input:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream& operator>>(basic_istream& (*__pf)(basic_istream&)) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_istream& operator>>(basic_istream& (*__pf)(basic_istream&)) {
return __pf(*this);
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream&
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_istream&
operator>>(basic_ios<char_type, traits_type>& (*__pf)(basic_ios<char_type, traits_type>&)) {
__pf(*this);
return *this;
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream& operator>>(ios_base& (*__pf)(ios_base&)) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_istream& operator>>(ios_base& (*__pf)(ios_base&)) {
__pf(*this);
return *this;
}
@@ -268,26 +268,26 @@ public:
_LIBCPP_HIDE_FROM_ABI streamsize gcount() const { return __gc_; }
int_type get();
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream& get(char_type& __c) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_istream& get(char_type& __c) {
int_type __ch = get();
if (__ch != traits_type::eof())
__c = traits_type::to_char_type(__ch);
return *this;
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream& get(char_type* __s, streamsize __n) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_istream& get(char_type* __s, streamsize __n) {
return get(__s, __n, this->widen('\n'));
}
basic_istream& get(char_type* __s, streamsize __n, char_type __dlm);
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream& get(basic_streambuf<char_type, traits_type>& __sb) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_istream& get(basic_streambuf<char_type, traits_type>& __sb) {
return get(__sb, this->widen('\n'));
}
basic_istream& get(basic_streambuf<char_type, traits_type>& __sb, char_type __dlm);
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream& getline(char_type* __s, streamsize __n) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_istream& getline(char_type* __s, streamsize __n) {
return getline(__s, __n, this->widen('\n'));
}
@@ -1184,7 +1184,7 @@ public:
typedef typename traits_type::off_type off_type;
// constructor/destructor
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 explicit basic_iostream(basic_streambuf<char_type, traits_type>* __sb)
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 explicit basic_iostream(basic_streambuf<char_type, traits_type>* __sb)
: basic_istream<_CharT, _Traits>(__sb) {}
~basic_iostream() override;
@@ -1195,7 +1195,7 @@ protected:
// assign/swap
inline _LIBCPP_HIDE_FROM_ABI basic_iostream& operator=(basic_iostream&& __rhs);
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void swap(basic_iostream& __rhs) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void swap(basic_iostream& __rhs) {
basic_istream<char_type, traits_type>::swap(__rhs);
}
};
diff --git a/libcxx/include/streambuf b/libcxx/include/streambuf
index 7dc4e31cc2324..964dab2b8959d 100644
--- a/libcxx/include/streambuf
+++ b/libcxx/include/streambuf
@@ -150,35 +150,35 @@ public:
virtual ~basic_streambuf() {}
// 27.6.2.2.1 locales:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 locale pubimbue(const locale& __loc) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 locale pubimbue(const locale& __loc) {
imbue(__loc);
locale __r = __loc_;
__loc_ = __loc;
return __r;
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 locale getloc() const { return __loc_; }
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 locale getloc() const { return __loc_; }
// 27.6.2.2.2 buffer and positioning:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_streambuf* pubsetbuf(char_type* __s, streamsize __n) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_streambuf* pubsetbuf(char_type* __s, streamsize __n) {
return setbuf(__s, __n);
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 pos_type
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 pos_type
pubseekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which = ios_base::in | ios_base::out) {
return seekoff(__off, __way, __which);
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 pos_type
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 pos_type
pubseekpos(pos_type __sp, ios_base::openmode __which = ios_base::in | ios_base::out) {
return seekpos(__sp, __which);
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int pubsync() { return sync(); }
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int pubsync() { return sync(); }
// Get and put areas:
// 27.6.2.2.3 Get area:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 streamsize in_avail() {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 streamsize in_avail() {
__check_invariants();
auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });
@@ -187,7 +187,7 @@ public:
return showmanyc();
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type snextc() {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type snextc() {
__check_invariants();
auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });
@@ -196,7 +196,7 @@ public:
return sgetc();
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sbumpc() {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sbumpc() {
__check_invariants();
auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });
@@ -207,7 +207,7 @@ public:
return __c;
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sgetc() {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sgetc() {
__check_invariants();
auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });
@@ -216,10 +216,10 @@ public:
return traits_type::to_int_type(*gptr());
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 streamsize sgetn(char_type* __s, streamsize __n) { return xsgetn(__s, __n); }
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 streamsize sgetn(char_type* __s, streamsize __n) { return xsgetn(__s, __n); }
// 27.6.2.2.4 Putback:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sputbackc(char_type __c) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sputbackc(char_type __c) {
__check_invariants();
auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });
@@ -229,7 +229,7 @@ public:
return traits_type::to_int_type(*gptr());
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sungetc() {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sungetc() {
__check_invariants();
auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });
@@ -240,7 +240,7 @@ public:
}
// 27.6.2.2.5 Put area:
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sputc(char_type __c) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sputc(char_type __c) {
__check_invariants();
auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });
@@ -251,7 +251,7 @@ public:
return traits_type::to_int_type(__c);
}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 streamsize sputn(const char_type* __s, streamsize __n) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 streamsize sputn(const char_type* __s, streamsize __n) {
return xsputn(__s, __n);
}
@@ -292,12 +292,12 @@ protected:
_LIBCPP_HIDE_FROM_ABI char_type* gptr() const { return __ninp_; }
_LIBCPP_HIDE_FROM_ABI char_type* egptr() const { return __einp_; }
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void gbump(int __n) { __ninp_ += __n; }
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void gbump(int __n) { __ninp_ += __n; }
// gbump takes an int, so it might not be able to represent the offset we want to add.
_LIBCPP_HIDE_FROM_ABI void __gbump_ptrdiff(ptrdiff_t __n) { __ninp_ += __n; }
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void setg(char_type* __gbeg, char_type* __gnext, char_type* __gend) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void setg(char_type* __gbeg, char_type* __gnext, char_type* __gend) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__gbeg, __gnext), "[gbeg, gnext) must be a valid range");
_LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__gbeg, __gend), "[gbeg, gend) must be a valid range");
_LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__gnext, __gend), "[gnext, gend) must be a valid range");
@@ -311,11 +311,11 @@ protected:
_LIBCPP_HIDE_FROM_ABI char_type* pptr() const { return __nout_; }
_LIBCPP_HIDE_FROM_ABI char_type* epptr() const { return __eout_; }
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void pbump(int __n) { __nout_ += __n; }
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void pbump(int __n) { __nout_ += __n; }
_LIBCPP_HIDE_FROM_ABI void __pbump(streamsize __n) { __nout_ += __n; }
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void setp(char_type* __pbeg, char_type* __pend) {
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void setp(char_type* __pbeg, char_type* __pend) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__pbeg, __pend), "[pbeg, pend) must be a valid range");
__bout_ = __nout_ = __pbeg;
__eout_ = __pend;
diff --git a/libcxx/include/valarray b/libcxx/include/valarray
index 215811d5ba475..a97b930eac4a7 100644
--- a/libcxx/include/valarray
+++ b/libcxx/include/valarray
@@ -793,7 +793,7 @@ private:
public:
// construct/destroy:
_LIBCPP_HIDE_FROM_ABI valarray() : __begin_(nullptr), __end_(nullptr) {}
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 explicit valarray(size_t __n);
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 explicit valarray(size_t __n);
_LIBCPP_HIDE_FROM_ABI valarray(const value_type& __x, size_t __n);
valarray(const value_type* __p, size_t __n);
valarray(const valarray& __v);
@@ -805,7 +805,7 @@ public:
valarray(const gslice_array<value_type>& __ga);
valarray(const mask_array<value_type>& __ma);
valarray(const indirect_array<value_type>& __ia);
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 ~valarray();
+ inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 ~valarray();
// assignment:
valarray& operator=(const valarray& __v);
diff --git a/libcxx/src/any.cpp b/libcxx/src/any.cpp
index f3fc715d517f2..47058f55d8248 100644
--- a/libcxx/src/any.cpp
+++ b/libcxx/src/any.cpp
@@ -14,6 +14,8 @@ const char* bad_any_cast::what() const noexcept { return "bad any cast"; }
#include <__config>
+#if _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 7
+
// Preserve std::experimental::any_bad_cast for ABI compatibility
// Even though it no longer exists in a header file
_LIBCPP_BEGIN_NAMESPACE_LFTS
@@ -25,4 +27,6 @@ class _LIBCPP_EXPORTED_FROM_ABI bad_any_cast : public bad_cast {
const char* bad_any_cast::what() const noexcept { return "bad any cast"; }
+#endif
+
_LIBCPP_END_NAMESPACE_LFTS
diff --git a/libcxx/src/charconv.cpp b/libcxx/src/charconv.cpp
index 5e8cb7d97703b..5438910a7e751 100644
--- a/libcxx/src/charconv.cpp
+++ b/libcxx/src/charconv.cpp
@@ -14,7 +14,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#ifndef _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
+#if _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 15
namespace __itoa {
@@ -24,7 +24,7 @@ _LIBCPP_EXPORTED_FROM_ABI char* __u64toa(uint64_t value, char* buffer) noexcept
} // namespace __itoa
-#endif // _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
+#endif // _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 15
// The original version of floating-point to_chars was written by Microsoft and
// contributed with the following license.
diff --git a/libcxx/src/condition_variable_destructor.cpp b/libcxx/src/condition_variable_destructor.cpp
index f6ffe33685990..fc4b4a601d964 100644
--- a/libcxx/src/condition_variable_destructor.cpp
+++ b/libcxx/src/condition_variable_destructor.cpp
@@ -14,7 +14,7 @@
#include <__config>
#include <__thread/support.h>
-#if _LIBCPP_ABI_VERSION == 1 || !_LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
+#if _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 9 || !_LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
# define NEEDS_CONDVAR_DESTRUCTOR
#endif
diff --git a/libcxx/src/error_category.cpp b/libcxx/src/error_category.cpp
index 8ae460fb5f1f4..9c0ca6a04a523 100644
--- a/libcxx/src/error_category.cpp
+++ b/libcxx/src/error_category.cpp
@@ -8,7 +8,9 @@
#include <__config>
-#ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
+// This has technically been removed in LLVM 3.4
+#if !defined(_LIBCPP_OBJECT_FORMAT_COFF) && !defined(_LIBCPP_OBJECT_FORMAT_XCOFF) && \
+ _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 4
# define _LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS
#endif
diff --git a/libcxx/src/memory.cpp b/libcxx/src/memory.cpp
index 9be40cb9c1285..e8631d0ad7e25 100644
--- a/libcxx/src/memory.cpp
+++ b/libcxx/src/memory.cpp
@@ -7,7 +7,8 @@
//===----------------------------------------------------------------------===//
#include <__config>
-#ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
+#if !defined(_LIBCPP_OBJECT_FORMAT_COFF) && !defined(_LIBCPP_OBJECT_FORMAT_XCOFF) && \
+ _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 5
# define _LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS
#endif
diff --git a/libcxx/src/mutex_destructor.cpp b/libcxx/src/mutex_destructor.cpp
index 9f991721f083f..4c63ea0da74da 100644
--- a/libcxx/src/mutex_destructor.cpp
+++ b/libcxx/src/mutex_destructor.cpp
@@ -19,7 +19,7 @@
#include <__config>
#include <__thread/support.h>
-#if _LIBCPP_ABI_VERSION == 1 || !_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION
+#if _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 9 || !_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION
# define NEEDS_MUTEX_DESTRUCTOR
#endif
diff --git a/libcxx/src/optional.cpp b/libcxx/src/optional.cpp
index faabe66cfcfc8..3b92580565bfc 100644
--- a/libcxx/src/optional.cpp
+++ b/libcxx/src/optional.cpp
@@ -19,6 +19,8 @@ const char* bad_optional_access::what() const noexcept { return "bad_optional_ac
#include <__config>
+#if _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 7
+
// Preserve std::experimental::bad_optional_access for ABI compatibility
// Even though it no longer exists in a header file
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
@@ -34,3 +36,5 @@ class _LIBCPP_EXPORTED_FROM_ABI bad_optional_access : public std::logic_error {
bad_optional_access::~bad_optional_access() noexcept = default;
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 7
diff --git a/libcxx/src/string.cpp b/libcxx/src/string.cpp
index 5028fc88fe46d..178ef710f0bcf 100644
--- a/libcxx/src/string.cpp
+++ b/libcxx/src/string.cpp
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
+#if _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 14
template <bool>
struct __basic_string_common;
@@ -35,12 +35,12 @@ struct __basic_string_common<true> {
void __basic_string_common<true>::__throw_length_error() const { std::__throw_length_error("basic_string"); }
void __basic_string_common<true>::__throw_out_of_range() const { std::__throw_out_of_range("basic_string"); }
-#endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
+#endif // _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 14
// Define legacy ABI functions
// ---------------------------
-#ifndef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
+#if _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 21
// This initializes the string with [__s, __s + __sz), but capacity() == __reserve. Assumes that __reserve >= __sz.
template <class _CharT, class _Traits, class _Allocator>
@@ -53,15 +53,12 @@ void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, si
__annotate_new(__sz);
}
-# define STRING_LEGACY_API(CharT) \
- template _LIBCPP_EXPORTED_FROM_ABI void basic_string<CharT>::__init(const value_type*, size_type, size_type)
-
-STRING_LEGACY_API(char);
+template _LIBCPP_EXPORTED_FROM_ABI void basic_string<char>::__init(const value_type*, size_type, size_type);
# if _LIBCPP_HAS_WIDE_CHARACTERS
-STRING_LEGACY_API(wchar_t);
+template _LIBCPP_EXPORTED_FROM_ABI void basic_string<wchar_t>::__init(const value_type*, size_type, size_type);
# endif
-#endif // _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
+#endif // _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 21
#define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template _LIBCPP_EXPORTED_FROM_ABI __VA_ARGS__;
#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
diff --git a/libcxx/src/valarray.cpp b/libcxx/src/valarray.cpp
index 6ef1f1cafc0e5..3d3a9ac30ebd0 100644
--- a/libcxx/src/valarray.cpp
+++ b/libcxx/src/valarray.cpp
@@ -10,8 +10,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-// These two symbols are part of the v1 ABI but not part of the >=v2 ABI.
-#if _LIBCPP_ABI_VERSION == 1
+#if _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 9
template _LIBCPP_EXPORTED_FROM_ABI valarray<size_t>::valarray(size_t);
template _LIBCPP_EXPORTED_FROM_ABI valarray<size_t>::~valarray();
#endif
diff --git a/libcxx/src/vector.cpp b/libcxx/src/vector.cpp
index 3f3a906d6421f..77a028a48077d 100644
--- a/libcxx/src/vector.cpp
+++ b/libcxx/src/vector.cpp
@@ -10,7 +10,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#ifndef _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
+#if _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 15
template <bool>
struct __vector_base_common;
@@ -25,6 +25,6 @@ void __vector_base_common<true>::__throw_length_error() const { std::__throw_len
void __vector_base_common<true>::__throw_out_of_range() const { std::__throw_out_of_range("vector"); }
-#endif // _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
+#endif // _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 15
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt
index 3dabd87b9c587..e9e2a3f374541 100644
--- a/libcxxabi/CMakeLists.txt
+++ b/libcxxabi/CMakeLists.txt
@@ -64,6 +64,9 @@ option(LIBCXXABI_HAS_WIN32_THREAD_API "Ignore auto-detection and force use of wi
option(LIBCXXABI_HAS_EXTERNAL_THREAD_API
"Build libc++abi with an externalized threading API.
This option may only be set to ON when LIBCXXABI_ENABLE_THREADS=ON." OFF)
+set(LIBCXXABI_AVAILABILITY_MINIMUM_HEADER_VERSION "1" CACHE STRING
+ "Minimum version of the libc++ headers that are allowed to be used by binaries linked against the libc++ library. This
+ version must correspond to the major version of an LLVM release.")
option(LIBCXXABI_ENABLE_FORGIVING_DYNAMIC_CAST
"Make dynamic_cast more forgiving when type_info's mistakenly have hidden \
visibility, and thus multiple type_infos can exist for a single type. \
@@ -321,6 +324,7 @@ add_definitions(-D_LIBCXXABI_BUILDING_LIBRARY)
# libcxxabi needs to, for various reasons, include the libcpp headers as if
# it is being built as part of libcxx.
add_definitions(-D_LIBCPP_BUILDING_LIBRARY)
+add_definitions(-D_LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION=${LIBCXXABI_AVAILABILITY_MINIMUM_HEADER_VERSION})
# Get feature flags.
add_compile_flags_if_supported(-fstrict-aliasing)
More information about the libcxx-commits
mailing list