scnlib  0.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
config.h
Go to the documentation of this file.
1 // Copyright 2017-2019 Elias Kosunen
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // This file is a part of scnlib:
16 // https://github.com/eliaskosunen/scnlib
17 
18 #ifndef SCN_DETAIL_CONFIG_H
19 #define SCN_DETAIL_CONFIG_H
20 
21 #include <cassert>
22 
23 #define SCN_STD_11 201103L
24 #define SCN_STD_14 201402L
25 #define SCN_STD_17 201703L
26 
27 #define SCN_COMPILER(major, minor, patch) \
28  ((major)*10000000 /* 10,000,000 */ + (minor)*10000 /* 10,000 */ + (patch))
29 #define SCN_VERSION SCN_COMPILER(0, 2, 0)
30 
31 #ifdef __INTEL_COMPILER
32 // Intel
33 #define SCN_INTEL \
34  SCN_COMPILER(__INTEL_COMPILER / 100, (__INTEL_COMPILER / 10) % 10, \
35  __INTEL_COMPILER % 10)
36 #elif defined(_MSC_VER) && defined(_MSC_FULL_VER)
37 // MSVC
38 #if _MSC_VER == _MSC_FULL_VER / 10000
39 #define SCN_MSVC \
40  SCN_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000)
41 #else
42 #define SCN_MSVC \
43  SCN_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 10, \
44  _MSC_FULL_VER % 100000)
45 #endif // _MSC_VER == _MSC_FULL_VER / 10000
46 #elif defined(__clang__) && defined(__clang_minor__) && \
47  defined(__clang_patchlevel__)
48 // Clang
49 #define SCN_CLANG \
50  SCN_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__)
51 #elif defined(__GNUC__) && defined(__GNUC_MINOR__) && \
52  defined(__GNUC_PATCHLEVEL__)
53 // GCC
54 #define SCN_GCC SCN_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
55 #endif
56 
57 #ifndef SCN_INTEL
58 #define SCN_INTEL 0
59 #endif
60 #ifndef SCN_MSVC
61 #define SCN_MSVC 0
62 #endif
63 #ifndef SCN_CLANG
64 #define SCN_CLANG 0
65 #endif
66 #ifndef SCN_GCC
67 #define SCN_GCC 0
68 #endif
69 
70 // Pretending to be gcc (clang, icc, etc.)
71 #ifdef __GNUC__
72 
73 #ifdef __GNUC_MINOR__
74 #define SCN_GCC_COMPAT_MINOR __GNUC_MINOR__
75 #else
76 #define SCN_GCC_COMPAT_MINOR 0
77 #endif
78 
79 #ifdef __GNUC_PATCHLEVEL__
80 #define SCN_GCC_COMPAT_PATCHLEVEL __GNUC_PATCHLEVEL__
81 #else
82 #define SCN_GCC_COMPAT_PATCHLEVEL 0
83 #endif
84 
85 #define SCN_GCC_COMPAT \
86  SCN_COMPILER(__GNUC__, SCN_GCC_COMPAT_MINOR, SCN_GCC_COMPAT_PATCHLEVEL)
87 #else
88 #define SCN_GCC_COMPAT 0
89 #endif // #ifdef __GNUC__
90 
91 #define SCN_STRINGIFY_APPLY(x) #x
92 #define SCN_STRINGIFY(x) SCN_STRINGIFY_APPLY(x)
93 
94 // POSIX
95 
96 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
97 #define SCN_POSIX 1
98 #else
99 #define SCN_POSIX 0
100 #endif
101 
102 // Windows
103 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && \
104  !defined(__CYGWIN__)
105 #define SCN_WINDOWS 1
106 #else
107 #define SCN_WINDOWS 0
108 #endif
109 
110 // Warning control
111 #if SCN_GCC
112 #define SCN_PRAGMA_APPLY(x) _Pragma(#x)
113 
114 #define SCN_GCC_PUSH _Pragma("GCC diagnostic push")
115 #define SCN_GCC_POP _Pragma("GCC diagnostic pop")
116 
117 #define SCN_GCC_IGNORE(x) SCN_PRAGMA_APPLY(GCC diagnostic ignored x)
118 #else
119 #define SCN_GCC_PUSH
120 #define SCN_GCC_POP
121 #define SCN_GCC_IGNORE(x)
122 #endif
123 
124 #if SCN_CLANG
125 #define SCN_PRAGMA_APPLY(x) _Pragma(#x)
126 
127 #define SCN_CLANG_PUSH _Pragma("clang diagnostic push")
128 #define SCN_CLANG_POP _Pragma("clang diagnostic pop")
129 
130 #define SCN_CLANG_IGNORE(x) SCN_PRAGMA_APPLY(clang diagnostic ignored x)
131 
132 #if SCN_CLANG >= SCN_COMPILER(3, 9, 0)
133 #define SCN_CLANG_PUSH_IGNORE_UNDEFINED_TEMPLATE \
134  SCN_CLANG_PUSH SCN_CLANG_IGNORE("-Wundefined-func-template")
135 #define SCN_CLANG_POP_IGNORE_UNDEFINED_TEMPLATE SCN_CLANG_POP
136 #else
137 #define SCN_CLANG_PUSH_IGNORE_UNDEFINED_TEMPLATE
138 #define SCN_CLANG_POP_IGNORE_UNDEFINED_TEMPLATE
139 #endif
140 
141 #else
142 #define SCN_CLANG_PUSH
143 #define SCN_CLANG_POP
144 #define SCN_CLANG_IGNORE(x)
145 #define SCN_CLANG_PUSH_IGNORE_UNDEFINED_TEMPLATE
146 #define SCN_CLANG_POP_IGNORE_UNDEFINED_TEMPLATE
147 #endif
148 
149 #if SCN_MSVC
150 #define SCN_MSVC_PUSH __pragma(warning(push))
151 #define SCN_MSVC_POP __pragma(warning(pop))
152 
153 #define SCN_MSVC_IGNORE(x) __pragma(warning(disable : x))
154 #else
155 #define SCN_MSVC_PUSH
156 #define SCN_MSVC_POP
157 #define SCN_MSVC_IGNORE(x)
158 #endif
159 
160 #ifndef SCN_PREDEFINE_VSCAN_OVERLOADS
161 #define SCN_PREDEFINE_VSCAN_OVERLOADS 0
162 #endif
163 
164 #ifdef __cpp_exceptions
165 #define SCN_HAS_EXCEPTIONS 1
166 #endif
167 #if !defined(SCN_HAS_EXCEPTIONS) && defined(__EXCEPTIONS)
168 #define SCN_HAS_EXCEPTIONS 1
169 #endif
170 #if !defined(SCN_HAS_EXCEPTIONS) && defined(_HAS_EXCEPTIONS)
171 #define SCN_HAS_EXCEPTIONS 1
172 #endif
173 #if !defined(SCN_HAS_EXCEPTIONS) && !defined(_CPPUNWIND)
174 #define SCN_HAS_EXCEPTIONS 0
175 #endif
176 #ifndef SCN_HAS_EXCEPTIONS
177 #define SCN_HAS_EXCEPTIONS 0
178 #endif
179 
180 #if SCN_HAS_EXCEPTIONS
181 #define SCN_TRY try
182 #define SCN_CATCH(x) catch (x)
183 #define SCN_THROW(x) throw x
184 #define SCN_RETHROW throw
185 #else
186 #define SCN_TRY if (true)
187 #define SCN_CATCH(x) if (false)
188 #define SCN_THROW(x) ::std::abort()
189 #define SCN_RETHROW ::std::abort()
190 #endif
191 
192 #ifdef __has_include
193 #define SCN_HAS_INCLUDE(x) __has_include(x)
194 #else
195 #define SCN_HAS_INCLUDE(x) 0
196 #endif
197 
198 #ifdef __has_cpp_attribute
199 #define SCN_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
200 #else
201 #define SCN_HAS_CPP_ATTRIBUTE(x) 0
202 #endif
203 
204 #ifdef __has_feature
205 #define SCN_HAS_FEATURE(x) __has_feature(x)
206 #else
207 #define SCN_HAS_FEATURE(x) 0
208 #endif
209 
210 #ifdef __has_builtin
211 #define SCN_HAS_BUILTIN(x) __has_builtin(x)
212 #else
213 #define SCN_HAS_BUILTIN(x) 0
214 #endif
215 
216 // Detect constexpr
217 #if defined(__cpp_constexpr)
218 #if __cpp_constexpr >= 201304
219 #define SCN_HAS_RELAXED_CONSTEXPR 1
220 #else
221 #define SCN_HAS_RELAXED_CONSTEXPR 0
222 #endif
223 #endif
224 
225 #ifndef SCN_HAS_RELAXED_CONSTEXPR
226 #if SCN_HAS_FEATURE(cxx_relaxed_constexpr) || \
227  SCN_MSVC >= SCN_COMPILER(19, 10, 0) || \
228  ((SCN_GCC >= SCN_COMPILER(6, 0, 0) || \
229  SCN_INTEL >= SCN_COMPILER(17, 0, 0)) && \
230  __cplusplus >= SCN_STD_14)
231 #define SCN_HAS_RELAXED_CONSTEXPR 1
232 #else
233 #define SCN_HAS_RELAXED_CONSTEXPR 0
234 #endif
235 #endif
236 
237 #if SCN_HAS_RELAXED_CONSTEXPR
238 #define SCN_CONSTEXPR14 constexpr
239 #else
240 #define SCN_CONSTEXPR14 inline
241 #endif
242 
243 // Detect string_view
244 #if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201603 && \
245  (__cplusplus >= SCN_STD_17 || SCN_MSVC_LANG >= SCN_STD_17)
246 #define SCN_HAS_STRING_VIEW 1
247 #else
248 #define SCN_HAS_STRING_VIEW 0
249 #endif
250 
251 // Detect [[nodiscard]]
252 #if (SCN_HAS_CPP_ATTRIBUTE(nodiscard) && __cplusplus >= SCN_STD_17) || \
253  (SCN_MSVC >= SCN_COMPILER(19, 11, 0) && SCN_MSVC_LANG >= SCN_STD_17) || \
254  ((SCN_GCC >= SCN_COMPILER(7, 0, 0) || \
255  SCN_INTEL >= SCN_COMPILER(18, 0, 0)) && \
256  __cplusplus >= SCN_STD_17)
257 #define SCN_NODISCARD [[nodiscard]]
258 #else
259 #define SCN_NODISCARD /*nodiscard*/
260 #endif
261 
262 // Detect [[clang::trivial_abi]]
263 #if SCN_HAS_CPP_ATTRIBUTE(clang::trivial_abi)
264 #define SCN_TRIVIAL_ABI [[clang::trivial_abi]]
265 #else
266 #define SCN_TRIVIAL_ABI /*trivial_abi*/
267 #endif
268 
269 #if defined(SCN_HEADER_ONLY) && SCN_HEADER_ONLY
270 #define SCN_FUNC inline
271 #else
272 #define SCN_FUNC
273 #endif
274 
275 // Detect <charconv>
276 #if (defined(__cpp_lib_to_chars) && __cpp_lib_to_chars >= 201606) || \
277  (SCN_HAS_INCLUDE(<charconv>) && __cplusplus >= SCN_STD_17)
278 
279 #if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 9
280 #define SCN_HAS_INTEGER_CHARCONV 1
281 #define SCN_HAS_FLOAT_CHARCONV 0
282 #elif SCN_MSVC >= SCN_COMPILER(19, 14, 0)
283 #define SCN_HAS_INTEGER_CHARCONV 1
284 
285 #if SCN_MSVC >= SCN_COMPILER(19, 21, 0)
286 #define SCN_HAS_FLOAT_CHARCONV 1
287 #else
288 #define SCN_HAS_FLOAT_CHARCONV 0
289 #endif
290 
291 #endif // _GLIBCXX_RELEASE
292 #endif // __cpp_lib_to_chars
293 
294 #ifndef SCN_HAS_INTEGER_CHARCONV
295 #define SCN_HAS_INTEGER_CHARCONV 0
296 #define SCN_HAS_FLOAT_CHARCONV 0
297 #endif
298 
299 // Detect std::launder
300 #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
301 #define SCN_HAS_LAUNDER 1
302 #else
303 #define SCN_HAS_LAUNDER 0
304 #endif
305 
306 // Detect void_t
307 #if defined(__cpp_lib_void_t) && __cpp_lib_void_t >= 201411
308 #define SCN_HAS_VOID_T 1
309 #else
310 #define SCN_HAS_VOID_T 0
311 #endif
312 
313 // Detect __assume
314 #if SCN_INTEL || SCN_MSVC
315 #define SCN_HAS_ASSUME 1
316 #else
317 #define SCN_HAS_ASSUME 0
318 #endif
319 
320 // Detect __builtin_assume
321 #if SCN_HAS_BUILTIN(__builtin_assume)
322 #define SCN_HAS_BUILTIN_ASSUME 1
323 #else
324 #define SCN_HAS_BUILTIN_ASSUME 0
325 #endif
326 
327 // Detect __builtin_unreachable
328 #if SCN_HAS_BUILTIN(__builtin_unreachable) || SCN_GCC_COMPAT
329 #define SCN_HAS_BUILTIN_UNREACHABLE 1
330 #else
331 #define SCN_HAS_BUILTIN_UNREACHABLE 0
332 #endif
333 
334 #if SCN_HAS_ASSUME
335 #define SCN_ASSUME(x) __assume(x)
336 #elif SCN_HAS_BUILTIN_ASSUME
337 #define SCN_ASSUME(x) __builtin_assume(x)
338 #elif SCN_HAS_BUILTIN_UNREACHABLE
339 #define SCN_ASSUME(x) ((x) ? static_cast<void>(0) : __builtin_unreachable())
340 #else
341 #define SCN_ASSUME(x) static_cast<void>((x) ? 0 : 0)
342 #endif
343 
344 #if SCN_HAS_BUILTIN_UNREACHABLE
345 #define SCN_UNREACHABLE __builtin_unreachable()
346 #else
347 #define SCN_UNREACHABLE SCN_ASSUME(0)
348 #endif
349 
350 // Detect __builtin_expect
351 #if SCN_HAS_BUILTIN(__builtin_expect) || SCN_GCC_COMPAT
352 #define SCN_HAS_BUILTIN_EXPECT 1
353 #else
354 #define SCN_HAS_BUILTIN_EXPECT 0
355 #endif
356 
357 #if SCN_HAS_BUILTIN_EXPECT
358 #define SCN_LIKELY(x) __builtin_expect(!!(x), 1)
359 #define SCN_UNLIKELY(x) __builtin_expect(!!(x), 0)
360 #else
361 #define SCN_LIKELY(x) (x)
362 #define SCN_UNLIKELY(x) (x)
363 #endif
364 
365 #ifndef SCN_DEPRECATED
366 
367 #if (SCN_HAS_CPP_ATTRIBUTE(deprecated) && __cplusplus >= 201402L) || \
368  SCN_MSVC >= SCN_COMPILER(19, 0, 0)
369 #define SCN_DEPRECATED [[deprecated]]
370 #else
371 
372 #if SCN_GCC_COMPAT
373 #define SCN_DEPRECATED __attribute__((deprecated))
374 #elif SCN_MSVC
375 #define SCN_DEPRECATED __declspec(deprecated)
376 #else
377 #define SCN_DEPRECATED /* deprecated */
378 #endif
379 
380 #endif
381 
382 #endif // !defined(SCN_DEPRECATED)
383 
384 #define SCN_UNUSED(x) static_cast<void>(sizeof(x))
385 
386 #if SCN_HAS_RELAXED_CONSTEXPR
387 #define SCN_ASSERT(cond, msg) \
388  do { \
389  static_cast<void>(SCN_LIKELY(cond)); \
390  assert((cond) && msg); \
391  } while (false)
392 #define SCN_EXPECT(cond) SCN_ASSERT(cond, "Precondition violation")
393 #define SCN_ENSURE(cond) SCN_ASSERT(cond, "Postcondition violation")
394 #else
395 #define SCN_ASSERT(cond, msg)
396 #define SCN_EXPECT(cond)
397 #define SCN_ENSURE(cond)
398 #endif
399 
400 #define SCN_BEGIN_NAMESPACE inline namespace v0 {
401 #define SCN_END_NAMESPACE }
402 
403 #endif // SCN_DETAIL_CONFIG_H