GCC Code Coverage Report


Directory: include/spy/
File: include/spy/libc.hpp
Date: 2026-10-08 16:24:54
Exec Total Coverage
Lines: 2 2 100.0%
Functions: 1 1 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 //==================================================================================================
2 /*
3 SPY - C++ Informations Broker
4 Copyright : SPY Project Contributors
5 SPDX-License-Identifier: BSL-1.0
6 */
7 //==================================================================================================
8 #pragma once
9
10 // Make sure the proper header is included to detect GNU libc
11 #include <spy/detail.hpp>
12
13 #include <compare>
14 #include <cstddef>
15
16 namespace spy::_
17 {
18 enum class libC
19 {
20 undefined_ = -1,
21 cloudabi_,
22 uc_,
23 vms_,
24 zos_,
25 gnu_
26 };
27
28 template<libC Lib, int M, int N, int P> struct libc_info
29 {
30 static constexpr libC vendor = Lib;
31 static constexpr version_id<M, N, P> version = {};
32
33 inline constexpr explicit operator bool() const noexcept;
34
35 template<libC C2> constexpr bool operator==(libc_info<C2, -1, 0, 0> const&) const noexcept
36 {
37 return C2 == vendor;
38 }
39
40 template<libC C2, int M2, int N2, int P2>
41 constexpr bool operator==(libc_info<C2, M2, N2, P2> const& c2) const noexcept
42 {
43 return C2 == vendor && version == c2.version;
44 }
45
46 template<libC C2, int M2, int N2, int P2>
47 constexpr auto operator<=>(libc_info<C2, M2, N2, P2> const& c2) const noexcept
48 {
49 if constexpr(vendor == C2) return version <=> c2.version;
50 else return vendor <=> C2;
51 }
52 };
53
54 template<_::stream OS, libC C, int M, int N, int P>
55 1 auto& operator<<(OS& os, libc_info<C, M, N, P> const& c)
56 {
57 if(c.vendor == libC::cloudabi_) return os << "CloudABI Standard C Library " << c.version;
58 if(c.vendor == libC::uc_) return os << "uClibc Standard C Library " << c.version;
59 if(c.vendor == libC::vms_) return os << "VMS Standard C Library " << c.version;
60 if(c.vendor == libC::zos_) return os << "z/OS Standard C Library " << c.version;
61 1 if(c.vendor == libC::gnu_) return os << "GNU Standard C Library " << c.version;
62
63 return os << "Undefined Standard C Library";
64 }
65
66 template<int M, int N, int P> using cloudabi_t = libc_info<libC::cloudabi_, M, N, P>;
67 template<int M, int N, int P> using uc_t = libc_info<libC::uc_, M, N, P>;
68 template<int M, int N, int P> using vms_t = libc_info<libC::vms_, M, N, P>;
69 template<int M, int N, int P> using zos_t = libc_info<libC::zos_, M, N, P>;
70 template<int M, int N, int P> using gnu_t = libc_info<libC::gnu_, M, N, P>;
71 }
72
73 namespace spy
74 {
75 //================================================================================================
76 // LIBC detection object type
77 //================================================================================================
78 #if defined(__cloudlibc__)
79 #define SPY_LIBC_IS_CLOUDABI
80 using libc_type = _::cloudabi_t<__cloudlibc_major__, __cloudlibc_minor__, 0>;
81 #elif defined(__GLIBC__)
82 #define SPY_LIBC_IS_GNU
83 using libc_type = _::gnu_t<__GLIBC__, __GLIBC_MINOR__, 0>;
84 #elif defined(__GNU_LIBRARY__)
85 #define SPY_LIBC_IS_GNU
86 using libc_type = _::gnu_t<__GNU_LIBRARY__, __GNU_LIBRARY_MINOR__, 0>;
87 #elif defined(__UCLIBC__)
88 #define SPY_LIBC_IS_UCLIBC
89 using libc_type = _::uc_t<__UCLIBC_MAJOR__, __UCLIBC_MINOR__, __UCLIBC_SUBLEVEL__>;
90 #elif defined(__CRTL_VER)
91 #define SPY_LIBC_IS_VMS
92 #define SPY0 (__CRTL_VER / 100)
93 using libc_type = _::vms_t<(SPY0 / 100000) % 100, (SPY0 / 1000) % 100, (SPY0) % 100>;
94 #undef SPY0
95 #elif defined(__LIBREL__)
96 #define SPY_LIBC_IS_ZOS
97 using libc_type = _::zos_t < (__LIBREL__ & 0xF000000) >> 24, (__LIBREL__ & 0xFF0000) >> 16,
98 (__LIBREL__ & 0xFFFF) > ;
99 #else
100 #define SPY_LIBC_IS_UNKNOWN
101 using libc_type = _::libc_info<_::libC::undefined_, -1, 0, 0>;
102 #endif
103
104 //================================================================================================
105 //! @ingroup spy_standards
106 //! @brief LIBC version reporting value
107 //!
108 //! The `spy::libc` object can be compared to any other libc related value to verify
109 //! if the code being compiled with a specific version of the libc.
110 //!
111 //! Any libc related value can be checked for equality or ordering for a given version. The
112 //! targeted version is then specified using a libc-dependent literal.
113 //!
114 //! Additionally, any of the libc related value are convertible to `bool`. They evaluates to
115 //! `true` if they matches the correct libc currently used.
116 //!
117 //! @groupheader{Supported Value}
118 //!
119 //! Name | Vendor
120 //! ----------------- | -------------
121 //! `spy::cloudabi_` | CloudABI
122 //! `spy::uc_` | uClibc
123 //! `spy::vms_` | VMS
124 //! `spy::zos_` | zOS
125 //! `spy::gnu_` | GNU
126 //!
127 //! @groupheader{Example}
128 //! @godbolt{samples/libc.cpp}
129 //================================================================================================
130 constexpr inline auto libc = libc_type {};
131 }
132
133 namespace spy::_
134 {
135 template<libC C, int M, int N, int P>
136 inline constexpr libc_info<C, M, N, P>::operator bool() const noexcept
137 {
138 return spy::libc == *this;
139 }
140 }
141
142 namespace spy
143 {
144 //================================================================================================
145 // LIBCs detector stand-alone instances
146 //================================================================================================
147 constexpr inline auto cloudabi_ = _::cloudabi_t<-1, 0, 0> {};
148 constexpr inline auto uc_ = _::uc_t<-1, 0, 0> {};
149 constexpr inline auto vms_ = _::vms_t<-1, 0, 0> {};
150 constexpr inline auto zos_ = _::zos_t<-1, 0, 0> {};
151 constexpr inline auto gnu_ = _::gnu_t<-1, 0, 0> {};
152 }
153
154 namespace spy::literal
155 {
156 //! @ingroup spy_standards
157 //! @brief User-defined suffix for the CloudABI libc version definition
158 template<char... c> constexpr auto operator""_cloud()
159 {
160 return _::literal_wrap<_::cloudabi_t, c...>();
161 }
162
163 //! @ingroup spy_standards
164 //! @brief User-defined suffix for the uClibc version definition
165 template<char... c> constexpr auto operator""_uc() { return _::literal_wrap<_::uc_t, c...>(); }
166
167 //! @ingroup spy_standards
168 //! @brief User-defined suffix for the VMS libc version definition
169 template<char... c> constexpr auto operator""_vms() { return _::literal_wrap<_::vms_t, c...>(); }
170
171 //! @ingroup spy_standards
172 //! @brief User-defined suffix for the zOS libc version definition
173 template<char... c> constexpr auto operator""_zos() { return _::literal_wrap<_::zos_t, c...>(); }
174
175 //! @ingroup spy_standards
176 //! @brief User-defined suffix for the GNU libc version definition
177 template<char... c> constexpr auto operator""_gnu() { return _::literal_wrap<_::gnu_t, c...>(); }
178 }
179