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 #ifdef _MSVC_LANG
111 #define SCN_MSVC_LANG _MSVC_LANG
112 #else
113 #define SCN_MSVC_LANG 0
114 #endif
115 
116 // Warning control
117 #if SCN_GCC
118 #define SCN_PRAGMA_APPLY(x) _Pragma(#x)
119 
120 #define SCN_GCC_PUSH _Pragma("GCC diagnostic push")
121 #define SCN_GCC_POP _Pragma("GCC diagnostic pop")
122 
123 #define SCN_GCC_IGNORE(x) SCN_PRAGMA_APPLY(GCC diagnostic ignored x)
124 #else
125 #define SCN_GCC_PUSH
126 #define SCN_GCC_POP
127 #define SCN_GCC_IGNORE(x)
128 #endif
129 
130 #if SCN_CLANG
131 #define SCN_PRAGMA_APPLY(x) _Pragma(#x)
132 
133 #define SCN_CLANG_PUSH _Pragma("clang diagnostic push")
134 #define SCN_CLANG_POP _Pragma("clang diagnostic pop")
135 
136 #define SCN_CLANG_IGNORE(x) SCN_PRAGMA_APPLY(clang diagnostic ignored x)
137 
138 #if SCN_CLANG >= SCN_COMPILER(3, 9, 0)
139 #define SCN_CLANG_PUSH_IGNORE_UNDEFINED_TEMPLATE \
140  SCN_CLANG_PUSH SCN_CLANG_IGNORE("-Wundefined-func-template")
141 #define SCN_CLANG_POP_IGNORE_UNDEFINED_TEMPLATE SCN_CLANG_POP
142 #else
143 #define SCN_CLANG_PUSH_IGNORE_UNDEFINED_TEMPLATE
144 #define SCN_CLANG_POP_IGNORE_UNDEFINED_TEMPLATE
145 #endif
146 
147 #else
148 #define SCN_CLANG_PUSH
149 #define SCN_CLANG_POP
150 #define SCN_CLANG_IGNORE(x)
151 #define SCN_CLANG_PUSH_IGNORE_UNDEFINED_TEMPLATE
152 #define SCN_CLANG_POP_IGNORE_UNDEFINED_TEMPLATE
153 #endif
154 
155 #if SCN_MSVC
156 #define SCN_MSVC_PUSH __pragma(warning(push))
157 #define SCN_MSVC_POP __pragma(warning(pop))
158 
159 #define SCN_MSVC_IGNORE(x) __pragma(warning(disable : x))
160 #else
161 #define SCN_MSVC_PUSH
162 #define SCN_MSVC_POP
163 #define SCN_MSVC_IGNORE(x)
164 #endif
165 
166 #ifndef SCN_PREDEFINE_VSCAN_OVERLOADS
167 #define SCN_PREDEFINE_VSCAN_OVERLOADS 0
168 #endif
169 
170 #ifdef __cpp_exceptions
171 #define SCN_HAS_EXCEPTIONS 1
172 #endif
173 #if !defined(SCN_HAS_EXCEPTIONS) && defined(__EXCEPTIONS)
174 #define SCN_HAS_EXCEPTIONS 1
175 #endif
176 #if !defined(SCN_HAS_EXCEPTIONS) && defined(_HAS_EXCEPTIONS)
177 #define SCN_HAS_EXCEPTIONS 1
178 #endif
179 #if !defined(SCN_HAS_EXCEPTIONS) && !defined(_CPPUNWIND)
180 #define SCN_HAS_EXCEPTIONS 0
181 #endif
182 #ifndef SCN_HAS_EXCEPTIONS
183 #define SCN_HAS_EXCEPTIONS 0
184 #endif
185 
186 #if SCN_HAS_EXCEPTIONS
187 #define SCN_TRY try
188 #define SCN_CATCH(x) catch (x)
189 #define SCN_THROW(x) throw x
190 #define SCN_RETHROW throw
191 #else
192 #define SCN_TRY if (true)
193 #define SCN_CATCH(x) if (false)
194 #define SCN_THROW(x) ::std::abort()
195 #define SCN_RETHROW ::std::abort()
196 #endif
197 
198 #ifdef __has_include
199 #define SCN_HAS_INCLUDE(x) __has_include(x)
200 #else
201 #define SCN_HAS_INCLUDE(x) 0
202 #endif
203 
204 #ifdef __has_cpp_attribute
205 #define SCN_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
206 #else
207 #define SCN_HAS_CPP_ATTRIBUTE(x) 0
208 #endif
209 
210 #ifdef __has_feature
211 #define SCN_HAS_FEATURE(x) __has_feature(x)
212 #else
213 #define SCN_HAS_FEATURE(x) 0
214 #endif
215 
216 #ifdef __has_builtin
217 #define SCN_HAS_BUILTIN(x) __has_builtin(x)
218 #else
219 #define SCN_HAS_BUILTIN(x) 0
220 #endif
221 
222 // Detect constexpr
223 #if defined(__cpp_constexpr)
224 #if __cpp_constexpr >= 201304
225 #define SCN_HAS_RELAXED_CONSTEXPR 1
226 #else
227 #define SCN_HAS_RELAXED_CONSTEXPR 0
228 #endif
229 #endif
230 
231 #ifndef SCN_HAS_RELAXED_CONSTEXPR
232 #if SCN_HAS_FEATURE(cxx_relaxed_constexpr) || \
233  SCN_MSVC >= SCN_COMPILER(19, 10, 0) || \
234  ((SCN_GCC >= SCN_COMPILER(6, 0, 0) || \
235  SCN_INTEL >= SCN_COMPILER(17, 0, 0)) && \
236  __cplusplus >= SCN_STD_14)
237 #define SCN_HAS_RELAXED_CONSTEXPR 1
238 #else
239 #define SCN_HAS_RELAXED_CONSTEXPR 0
240 #endif
241 #endif
242 
243 #if SCN_HAS_RELAXED_CONSTEXPR
244 #define SCN_CONSTEXPR14 constexpr
245 #else
246 #define SCN_CONSTEXPR14 inline
247 #endif
248 
249 
250 // Detect string_view
251 #if SCN_HAS_INCLUDE(<string_view>)
252 #include <string_view>
253 #endif
254 
255 #if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201603 && \
256  (__cplusplus >= SCN_STD_17 || SCN_MSVC_LANG >= SCN_STD_17)
257 #define SCN_HAS_STRING_VIEW 1
258 #else
259 #define SCN_HAS_STRING_VIEW 0
260 #endif
261 
262 // Detect [[nodiscard]]
263 #if (SCN_HAS_CPP_ATTRIBUTE(nodiscard) && __cplusplus >= SCN_STD_17) || \
264  (SCN_MSVC >= SCN_COMPILER(19, 11, 0) && SCN_MSVC_LANG >= SCN_STD_17) || \
265  ((SCN_GCC >= SCN_COMPILER(7, 0, 0) || \
266  SCN_INTEL >= SCN_COMPILER(18, 0, 0)) && \
267  __cplusplus >= SCN_STD_17)
268 #define SCN_NODISCARD [[nodiscard]]
269 #else
270 #define SCN_NODISCARD /*nodiscard*/
271 #endif
272 
273 // Detect [[clang::trivial_abi]]
274 #if SCN_HAS_CPP_ATTRIBUTE(clang::trivial_abi)
275 #define SCN_TRIVIAL_ABI [[clang::trivial_abi]]
276 #else
277 #define SCN_TRIVIAL_ABI /*trivial_abi*/
278 #endif
279 
280 #if defined(SCN_HEADER_ONLY) && SCN_HEADER_ONLY
281 #define SCN_FUNC inline
282 #else
283 #define SCN_FUNC
284 #endif
285 
286 // Detect <charconv>
287 #if (defined(__cpp_lib_to_chars) && __cpp_lib_to_chars >= 201606) || \
288  (SCN_HAS_INCLUDE(<charconv>) && __cplusplus >= SCN_STD_17)
289 
290 #if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 9
291 #define SCN_HAS_INTEGER_CHARCONV 1
292 #define SCN_HAS_FLOAT_CHARCONV 0
293 #elif SCN_MSVC >= SCN_COMPILER(19, 14, 0)
294 #define SCN_HAS_INTEGER_CHARCONV 1
295 
296 #if SCN_MSVC >= SCN_COMPILER(19, 21, 0)
297 #define SCN_HAS_FLOAT_CHARCONV 1
298 #else
299 #define SCN_HAS_FLOAT_CHARCONV 0
300 #endif
301 
302 #endif // _GLIBCXX_RELEASE
303 #endif // __cpp_lib_to_chars
304 
305 #ifndef SCN_HAS_INTEGER_CHARCONV
306 #define SCN_HAS_INTEGER_CHARCONV 0
307 #define SCN_HAS_FLOAT_CHARCONV 0
308 #endif
309 
310 // Detect std::launder
311 #include <new>
312 #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
313 #define SCN_HAS_LAUNDER 1
314 #else
315 #define SCN_HAS_LAUNDER 0
316 #endif
317 
318 // Detect __assume
319 #if SCN_INTEL || SCN_MSVC
320 #define SCN_HAS_ASSUME 1
321 #else
322 #define SCN_HAS_ASSUME 0
323 #endif
324 
325 // Detect __builtin_assume
326 #if SCN_HAS_BUILTIN(__builtin_assume)
327 #define SCN_HAS_BUILTIN_ASSUME 1
328 #else
329 #define SCN_HAS_BUILTIN_ASSUME 0
330 #endif
331 
332 // Detect __builtin_unreachable
333 #if SCN_HAS_BUILTIN(__builtin_unreachable) || SCN_GCC_COMPAT
334 #define SCN_HAS_BUILTIN_UNREACHABLE 1
335 #else
336 #define SCN_HAS_BUILTIN_UNREACHABLE 0
337 #endif
338 
339 #if SCN_HAS_ASSUME
340 #define SCN_ASSUME(x) __assume(x)
341 #elif SCN_HAS_BUILTIN_ASSUME
342 #define SCN_ASSUME(x) __builtin_assume(x)
343 #elif SCN_HAS_BUILTIN_UNREACHABLE
344 #define SCN_ASSUME(x) ((x) ? static_cast<void>(0) : __builtin_unreachable())
345 #else
346 #define SCN_ASSUME(x) static_cast<void>((x) ? 0 : 0)
347 #endif
348 
349 #if SCN_HAS_BUILTIN_UNREACHABLE
350 #define SCN_UNREACHABLE __builtin_unreachable()
351 #else
352 #define SCN_UNREACHABLE SCN_ASSUME(0)
353 #endif
354 
355 // Detect __builtin_expect
356 #if SCN_HAS_BUILTIN(__builtin_expect) || SCN_GCC_COMPAT
357 #define SCN_HAS_BUILTIN_EXPECT 1
358 #else
359 #define SCN_HAS_BUILTIN_EXPECT 0
360 #endif
361 
362 #if SCN_HAS_BUILTIN_EXPECT
363 #define SCN_LIKELY(x) __builtin_expect(!!(x), 1)
364 #define SCN_UNLIKELY(x) __builtin_expect(!!(x), 0)
365 #else
366 #define SCN_LIKELY(x) (x)
367 #define SCN_UNLIKELY(x) (x)
368 #endif
369 
370 #ifndef SCN_DEPRECATED
371 
372 #if (SCN_HAS_CPP_ATTRIBUTE(deprecated) && __cplusplus >= 201402L) || \
373  SCN_MSVC >= SCN_COMPILER(19, 0, 0)
374 #define SCN_DEPRECATED [[deprecated]]
375 #else
376 
377 #if SCN_GCC_COMPAT
378 #define SCN_DEPRECATED __attribute__((deprecated))
379 #elif SCN_MSVC
380 #define SCN_DEPRECATED __declspec(deprecated)
381 #else
382 #define SCN_DEPRECATED /* deprecated */
383 #endif
384 
385 #endif
386 
387 #endif // !defined(SCN_DEPRECATED)
388 
389 #define SCN_UNUSED(x) static_cast<void>(sizeof(x))
390 
391 #if SCN_HAS_RELAXED_CONSTEXPR
392 #define SCN_ASSERT(cond, msg) \
393  do { \
394  static_cast<void>(SCN_LIKELY(cond)); \
395  assert((cond) && msg); \
396  } while (false)
397 #define SCN_EXPECT(cond) SCN_ASSERT(cond, "Precondition violation")
398 #define SCN_ENSURE(cond) SCN_ASSERT(cond, "Postcondition violation")
399 #else
400 #define SCN_ASSERT(cond, msg)
401 #define SCN_EXPECT(cond)
402 #define SCN_ENSURE(cond)
403 #endif
404 
405 #define SCN_BEGIN_NAMESPACE inline namespace v0 {
406 #define SCN_END_NAMESPACE }
407 
408 #endif // SCN_DETAIL_CONFIG_H