Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions include/asio/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1658,4 +1658,38 @@
# define ASIO_VERSIONED_NAME(name) asio_ ## name
#endif // defined(ASIO_VERSION_NAMESPACE)

// Named C++20 modules require CPOs (customization point objects) to have
// external linkage. The anonymous-namespace singleton idiom used by asio's
// prefer/require/query/require_concept CPOs creates TU-local entities that
// GCC 15+ (and future Clang in strict mode) reject when those headers are
// #included inside a named module's global module fragment.
//
// Define ASIO_CPO_INLINE_CONSTEXPR to replace the anonymous-namespace
// reference pattern with an inline constexpr variable. This is safe for all
// compilers: the impl types are stateless function objects with constexpr
// constructors, so `inline constexpr impl cpo{}` has identical ODR semantics.
// This flag is compiler-neutral; enable it for any C++20 named-module build.
#if !defined(ASIO_CPO_INLINE_CONSTEXPR) \
&& !defined(ASIO_DISABLE_CPO_INLINE_CONSTEXPR)
// Automatically activate when the user opts in via a build-system flag.
// In GCC named-module builds, pass -DASIO_GCC_NAMED_MODULES to trigger this.
# if defined(ASIO_GCC_NAMED_MODULES)
# define ASIO_CPO_INLINE_CONSTEXPR 1
# endif // defined(ASIO_GCC_NAMED_MODULES)
#endif // !defined(ASIO_CPO_INLINE_CONSTEXPR)

// Namespace-scope `const` variables (non-inline) have internal linkage in
// C++. When included in a named module's global module fragment they become
// TU-local entities; GCC 15+ rejects module functions that reference them.
// ASIO_DETAIL_CONSTEXPR_VAR expands to `inline constexpr` under
// ASIO_CPO_INLINE_CONSTEXPR, giving these variables external linkage and
// making them safe to reference from named modules.
// NOTE: this block must come AFTER the ASIO_CPO_INLINE_CONSTEXPR detection
// above so that the #if test is evaluated with the correct macro state.
#if defined(ASIO_CPO_INLINE_CONSTEXPR)
# define ASIO_DETAIL_CONSTEXPR_VAR inline constexpr
#else
# define ASIO_DETAIL_CONSTEXPR_VAR const
#endif // defined(ASIO_CPO_INLINE_CONSTEXPR)

#endif // ASIO_DETAIL_CONFIG_HPP
36 changes: 18 additions & 18 deletions include/asio/detail/socket_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ ASIO_INLINE_NAMESPACE_BEGIN
namespace detail {

#if defined(ASIO_WINDOWS_RUNTIME)
const int max_addr_v4_str_len = 256;
const int max_addr_v6_str_len = 256;
ASIO_DETAIL_CONSTEXPR_VAR int max_addr_v4_str_len = 256;
ASIO_DETAIL_CONSTEXPR_VAR int max_addr_v6_str_len = 256;
typedef unsigned __int32 u_long_type;
typedef unsigned __int16 u_short_type;
struct in4_addr_type { u_long_type s_addr; };
Expand Down Expand Up @@ -185,10 +185,10 @@ typedef int signed_size_type;
# define ASIO_OS_DEF_SA_NOCLDWAIT 0x4
#elif defined(ASIO_WINDOWS) || defined(ASIO_CYGWIN_W32_SOCKETS)
typedef SOCKET socket_type;
const SOCKET invalid_socket = INVALID_SOCKET;
const int socket_error_retval = SOCKET_ERROR;
const int max_addr_v4_str_len = 256;
const int max_addr_v6_str_len = 256;
ASIO_DETAIL_CONSTEXPR_VAR SOCKET invalid_socket = INVALID_SOCKET;
ASIO_DETAIL_CONSTEXPR_VAR int socket_error_retval = SOCKET_ERROR;
ASIO_DETAIL_CONSTEXPR_VAR int max_addr_v4_str_len = 256;
ASIO_DETAIL_CONSTEXPR_VAR int max_addr_v6_str_len = 256;
typedef sockaddr socket_addr_type;
typedef in_addr in4_addr_type;
typedef ip_mreq in4_mreq_type;
Expand Down Expand Up @@ -291,22 +291,22 @@ struct sockaddr_un_type { u_short sun_family; char sun_path[108]; };
# define ASIO_OS_DEF_AI_ADDRCONFIG 0
# endif
# if defined (_WIN32_WINNT)
const int max_iov_len = 64;
ASIO_DETAIL_CONSTEXPR_VAR int max_iov_len = 64;
# else
const int max_iov_len = 16;
ASIO_DETAIL_CONSTEXPR_VAR int max_iov_len = 16;
# endif
# define ASIO_OS_DEF_SA_RESTART 0x1
# define ASIO_OS_DEF_SA_NOCLDSTOP 0x2
# define ASIO_OS_DEF_SA_NOCLDWAIT 0x4
#else
typedef int socket_type;
const int invalid_socket = -1;
const int socket_error_retval = -1;
const int max_addr_v4_str_len = INET_ADDRSTRLEN;
ASIO_DETAIL_CONSTEXPR_VAR int invalid_socket = -1;
ASIO_DETAIL_CONSTEXPR_VAR int socket_error_retval = -1;
ASIO_DETAIL_CONSTEXPR_VAR int max_addr_v4_str_len = INET_ADDRSTRLEN;
#if defined(INET6_ADDRSTRLEN)
const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
ASIO_DETAIL_CONSTEXPR_VAR int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
#else // defined(INET6_ADDRSTRLEN)
const int max_addr_v6_str_len = 256;
ASIO_DETAIL_CONSTEXPR_VAR int max_addr_v6_str_len = 256;
#endif // defined(INET6_ADDRSTRLEN)
typedef sockaddr socket_addr_type;
typedef in_addr in4_addr_type;
Expand Down Expand Up @@ -412,10 +412,10 @@ typedef int signed_size_type;
# define ASIO_OS_DEF_AI_ADDRCONFIG 0
# endif
# if defined(IOV_MAX)
const int max_iov_len = IOV_MAX;
ASIO_DETAIL_CONSTEXPR_VAR int max_iov_len = IOV_MAX;
# else
// POSIX platforms are not required to define IOV_MAX.
const int max_iov_len = 16;
ASIO_DETAIL_CONSTEXPR_VAR int max_iov_len = 16;
# endif
# define ASIO_OS_DEF_SA_RESTART SA_RESTART
# define ASIO_OS_DEF_SA_NOCLDSTOP SA_NOCLDSTOP
Expand All @@ -425,9 +425,9 @@ const int max_iov_len = 16;
# define ASIO_OS_DEF_SA_NOCLDWAIT 0
# endif // defined(SA_NOCLDWAIT)
#endif
const int custom_socket_option_level = 0xA5100000;
const int enable_connection_aborted_option = 1;
const int always_fail_option = 2;
ASIO_DETAIL_CONSTEXPR_VAR int custom_socket_option_level = 0xA5100000;
ASIO_DETAIL_CONSTEXPR_VAR int enable_connection_aborted_option = 1;
ASIO_DETAIL_CONSTEXPR_VAR int always_fail_option = 2;

} // namespace detail
ASIO_INLINE_NAMESPACE_END
Expand Down
4 changes: 4 additions & 0 deletions include/asio/prefer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,12 +520,16 @@ const T static_instance<T>::instance = {};
} // namespace ASIO_VERSIONED_NAME(prefer_fn)
namespace asio {
ASIO_INLINE_NAMESPACE_BEGIN
#if defined(ASIO_CPO_INLINE_CONSTEXPR)
inline constexpr ASIO_VERSIONED_NAME(prefer_fn)::impl prefer{};
#else // defined(ASIO_CPO_INLINE_CONSTEXPR)
namespace {

static constexpr const ASIO_VERSIONED_NAME(prefer_fn)::impl&
prefer = ASIO_VERSIONED_NAME(prefer_fn)::static_instance<>::instance;

} // namespace
#endif // defined(ASIO_CPO_INLINE_CONSTEXPR)

typedef ASIO_VERSIONED_NAME(prefer_fn)::impl prefer_t;

Expand Down
4 changes: 4 additions & 0 deletions include/asio/query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,16 @@ const T static_instance<T>::instance = {};
} // namespace ASIO_VERSIONED_NAME(query_fn)
namespace asio {
ASIO_INLINE_NAMESPACE_BEGIN
#if defined(ASIO_CPO_INLINE_CONSTEXPR)
inline constexpr ASIO_VERSIONED_NAME(query_fn)::impl query{};
#else // defined(ASIO_CPO_INLINE_CONSTEXPR)
namespace {

static constexpr const ASIO_VERSIONED_NAME(query_fn)::impl&
query = ASIO_VERSIONED_NAME(query_fn)::static_instance<>::instance;

} // namespace
#endif // defined(ASIO_CPO_INLINE_CONSTEXPR)

typedef ASIO_VERSIONED_NAME(query_fn)::impl query_t;

Expand Down
4 changes: 4 additions & 0 deletions include/asio/require.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,12 +375,16 @@ const T static_instance<T>::instance = {};
} // namespace ASIO_VERSIONED_NAME(require_fn)
namespace asio {
ASIO_INLINE_NAMESPACE_BEGIN
#if defined(ASIO_CPO_INLINE_CONSTEXPR)
inline constexpr ASIO_VERSIONED_NAME(require_fn)::impl require{};
#else // defined(ASIO_CPO_INLINE_CONSTEXPR)
namespace {

static constexpr const ASIO_VERSIONED_NAME(require_fn)::impl&
require = ASIO_VERSIONED_NAME(require_fn)::static_instance<>::instance;

} // namespace
#endif // defined(ASIO_CPO_INLINE_CONSTEXPR)

typedef ASIO_VERSIONED_NAME(require_fn)::impl require_t;

Expand Down
4 changes: 4 additions & 0 deletions include/asio/require_concept.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,13 +285,17 @@ const T static_instance<T>::instance = {};
} // namespace ASIO_VERSIONED_NAME(require_concept_fn)
namespace asio {
ASIO_INLINE_NAMESPACE_BEGIN
#if defined(ASIO_CPO_INLINE_CONSTEXPR)
inline constexpr ASIO_VERSIONED_NAME(require_concept_fn)::impl require_concept{};
#else // defined(ASIO_CPO_INLINE_CONSTEXPR)
namespace {

static constexpr const ASIO_VERSIONED_NAME(require_concept_fn)::impl&
require_concept = ASIO_VERSIONED_NAME(
require_concept_fn)::static_instance<>::instance;

} // namespace
#endif // defined(ASIO_CPO_INLINE_CONSTEXPR)

typedef ASIO_VERSIONED_NAME(require_concept_fn)::impl require_concept_t;

Expand Down