[libcxx-commits] [libcxx] [libc++] Stabilize transitive includes for C++23 (PR #134143)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 3 13:37:27 PDT 2025


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/134143

>From 08e02bc5ff2286cb66b54e0a1a5ade6fcb9ae612 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 2 Apr 2025 15:20:11 -0400
Subject: [PATCH 1/3] [libc++] Stabilize transitive includes for C++23

Our mechanism to retain transitive includes for backwards compatibility
was previously not taking into account C++23: this means that users on
C++23 would not get any protection against the removal of transitive
includes. This was fine when C++23 was still not used widely.

However, now that C++23 is used pretty widely, we should start providing
transitive includes backwards compatibility for users of that language
mode too. This patch documents that requirement.

There are no actual changes to the code since we haven't removed
transitive includes since the last release. However, starting now,
we should guard any removal of transitive includes behind

    #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23

instead of

    #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
---
 libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst b/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst
index 02cbc162318ef..03b5f4ac4b5d6 100644
--- a/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst
+++ b/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst
@@ -38,7 +38,7 @@ guarded by something of the form:
 
 .. code-block:: cpp
 
-   #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
+   #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23
    #  include <algorithm>
    #  include <iterator>
    #  include <utility>
@@ -49,6 +49,9 @@ include transitive headers, regardless of the language version. This can be
 useful for users to aid the transition to a newer language version, or by users
 who simply want to make sure they include what they use in their code.
 
+We currently provide transitive inclusions for backwards compatibility in all
+Standard modes older than C++26.
+
 
 Rationale
 ---------

>From 4fa2006d7bae769e30aa7c1441fcc21e4c15ec71 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 2 Jul 2025 11:25:56 -0400
Subject: [PATCH 2/3] Update documentation per discussion

---
 .../docs/DesignDocs/HeaderRemovalPolicy.rst   | 30 ++++++++++++-------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst b/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst
index 03b5f4ac4b5d6..6d0cc2000e397 100644
--- a/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst
+++ b/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst
@@ -22,9 +22,10 @@ to port headers to platforms with reduced functionality.
 
 A disadvantage is that users unknowingly depend on these transitive includes.
 Thus removing an include might break their build after upgrading a newer
-version of libc++. For example, ``<algorithm>`` is often forgotten but using
-algorithms will still work through those transitive includes. This problem is
-solved by modules, however in practice most people do not use modules (yet).
+version of libc++ by reducing the set of declarations provided by a header.
+For example, ``<algorithm>`` is often forgotten but using algorithms will
+still work through those transitive includes. This problem is solved by modules,
+however in practice most people do not use modules (yet).
 
 To ease the removal of transitive includes in libc++, libc++ will remove
 unnecessary transitive includes in newly supported C++ versions. This means
@@ -33,8 +34,11 @@ newer version of the Standard. Libc++ also reserves the right to remove
 transitive includes at any other time, however new language versions will be
 used as a convenient way to perform bulk removals of transitive includes.
 
-For libc++ developers, this means that any transitive include removal must be
-guarded by something of the form:
+However, libc++ intends not to gratuitously break users on stable versions of
+the Standard. Hence, we intend to maintain backwards compatibility of the
+declarations we provide in a header, within reason. For libc++ developers, this
+means that any transitive include removal of a public header must be guarded by
+something of the form:
 
 .. code-block:: cpp
 
@@ -44,13 +48,17 @@ guarded by something of the form:
    #  include <utility>
    #endif
 
-When users define ``_LIBCPP_REMOVE_TRANSITIVE_INCLUDES``, libc++ will not
-include transitive headers, regardless of the language version. This can be
-useful for users to aid the transition to a newer language version, or by users
-who simply want to make sure they include what they use in their code.
+Occasionally, private headers may also be included transitively for backwards
+compatibility in the same manner.
 
-We currently provide transitive inclusions for backwards compatibility in all
-Standard modes older than C++26.
+When users define ``_LIBCPP_REMOVE_TRANSITIVE_INCLUDES``, libc++ will not include
+transitive headers, regardless of the language version. This can be useful for users
+to aid the transition to a newer language version, or by users who simply want to
+make sure they include what they use in their code.
+
+We currently strive to provide backwards compatibility on the set of declarations
+provided by a header in all Standard modes starting with C++23. Note that this is
+very difficult to actually enforce, so this is done only on a best effort basis.
 
 
 Rationale

>From c095b42f1bfcf651bc96bc83e892cfad0518f361 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 3 Jul 2025 16:37:17 -0400
Subject: [PATCH 3/3] Review comments

---
 libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst b/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst
index 6d0cc2000e397..e52b625fae8bc 100644
--- a/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst
+++ b/libcxx/docs/DesignDocs/HeaderRemovalPolicy.rst
@@ -36,7 +36,9 @@ used as a convenient way to perform bulk removals of transitive includes.
 
 However, libc++ intends not to gratuitously break users on stable versions of
 the Standard. Hence, we intend to maintain backwards compatibility of the
-declarations we provide in a header, within reason. For libc++ developers, this
+declarations we provide in a header, within reason. We reserve the right to
+break such backwards compatibility in the future, however we will strive to
+do it in a user-friendly way, again within reason. For libc++ developers, this
 means that any transitive include removal of a public header must be guarded by
 something of the form:
 
@@ -49,16 +51,17 @@ something of the form:
    #endif
 
 Occasionally, private headers may also be included transitively for backwards
-compatibility in the same manner.
+compatibility in the same manner. We currently strive to provide backwards
+compatibility on the set of declarations provided by a header in all Standard
+modes starting with **C++23**. Note that this is very difficult to actually
+enforce, so this is done only on a best effort basis.
 
 When users define ``_LIBCPP_REMOVE_TRANSITIVE_INCLUDES``, libc++ will not include
 transitive headers, regardless of the language version. This can be useful for users
 to aid the transition to a newer language version, or by users who simply want to
-make sure they include what they use in their code.
-
-We currently strive to provide backwards compatibility on the set of declarations
-provided by a header in all Standard modes starting with C++23. Note that this is
-very difficult to actually enforce, so this is done only on a best effort basis.
+make sure they include what they use in their code. However, note that defining this
+macro means that the set of declarations and transitive includes provided by the library
+may change from release to release, which can break your code.
 
 
 Rationale



More information about the libcxx-commits mailing list