https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124428

            Bug ID: 124428
           Summary: Reduce how often bits/version.h is re-included
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

The version.h header for defining feature test macros does not have include
guards, so that it can define a different set of macros each time it's
included, based on the state of other macros. But some of the macros it defines
are defined the same way every time.

Specifically, it works like this:

#if !defined(__cpp_lib_exchange_function)
# if (__cplusplus >= 201402L)
#  define __glibcxx_exchange_function 201304L
#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_exchange_function)
#   define __cpp_lib_exchange_function 201304L
#  endif
# endif
#endif /* !defined(__cpp_lib_exchange_function) */
#undef __glibcxx_want_exchange_function

The __glibcxx_exchange_function is for internal use and the
__cpp_lib_exchange_function is public for users (and required by the standard),
and is only defined by <utility> and <version>.

Whether the internal __glibcxx_exchange_function macro gets defined never
changes for a given TU no matter how many times bits/version.h is re-included.
But whether the public __cpp_lib_exchange_function macro gets defined depends
on whether the "want" macros are defined at the point of inclusion.

We include <bits/version.h> repeatedly across most of the library's other
headers, to ensure that we can check the __glibcxx_xxx macros everywhere we
might need to, and then in some headers we include it again after defining one
or more __glibcxx_want_xxx macros.

Currently <vector> includes bits/version.h 12 times!

We could reduce the number of times it gets re-included by including it once at
the end of <bits/c++config.h> (which is included everywhere already). Then
every header could just rely on the __glibcxx_xxx internal macros always being
defined. We would only need to re-include it in the standard headers like
<string> and <vector> when they want to define a __cpp_lib_xxx public macro.

Alternatively, we could split version.h into the "always defined" part that
defines the internal __glibcxx_xxx macros, and include that once everywhere,
and then have a separate header that only defines the public __cpp_lib_xxx
macros. That would mean duplicating all the #if conditionals though, so might
not be faster to preprocess.

Reply via email to