1 /*
2  * Copyright 2011-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <cstddef>
20 
21 #include <folly/portability/Config.h>
22 #include <folly/CPortability.h>
23 
24 // Unaligned loads and stores
25 namespace folly {
26 #if FOLLY_HAVE_UNALIGNED_ACCESS
27 constexpr bool kHasUnalignedAccess = true;
28 #else
29 constexpr bool kHasUnalignedAccess = false;
30 #endif
31 } // namespace folly
32 
33 // compiler specific attribute translation
34 // msvc should come first, so if clang is in msvc mode it gets the right defines
35 
36 // NOTE: this will only do checking in msvc with versions that support /analyze
37 #if _MSC_VER
38 #ifdef _USE_ATTRIBUTES_FOR_SAL
39 #undef _USE_ATTRIBUTES_FOR_SAL
40 #endif
41 /* nolint */
42 #define _USE_ATTRIBUTES_FOR_SAL 1
43 #include <sal.h> // @manual
44 #define FOLLY_PRINTF_FORMAT _Printf_format_string_
45 #define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) /**/
46 #else
47 #define FOLLY_PRINTF_FORMAT /**/
48 #define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) \
49   __attribute__((__format__(__printf__, format_param, dots_param)))
50 #endif
51 
52 // warn unused result
53 #if defined(__has_cpp_attribute)
54 #if __has_cpp_attribute(nodiscard)
55 #define FOLLY_NODISCARD [[nodiscard]]
56 #endif
57 #endif
58 #if !defined FOLLY_NODISCARD
59 #if defined(_MSC_VER) && (_MSC_VER >= 1700)
60 #define FOLLY_NODISCARD _Check_return_
61 #elif defined(__clang__) || defined(__GNUC__)
62 #define FOLLY_NODISCARD __attribute__((__warn_unused_result__))
63 #else
64 #define FOLLY_NODISCARD
65 #endif
66 #endif
67 
68 // target
69 #ifdef _MSC_VER
70 #define FOLLY_TARGET_ATTRIBUTE(target)
71 #else
72 #define FOLLY_TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
73 #endif
74 
75 // detection for 64 bit
76 #if defined(__x86_64__) || defined(_M_X64)
77 #define FOLLY_X64 1
78 #else
79 #define FOLLY_X64 0
80 #endif
81 
82 #if defined(__arm__)
83 #define FOLLY_ARM 1
84 #else
85 #define FOLLY_ARM 0
86 #endif
87 
88 #if defined(__aarch64__)
89 #define FOLLY_AARCH64 1
90 #else
91 #define FOLLY_AARCH64 0
92 #endif
93 
94 #if defined(__powerpc64__)
95 #define FOLLY_PPC64 1
96 #else
97 #define FOLLY_PPC64 0
98 #endif
99 
100 namespace folly {
101 constexpr bool kIsArchArm = FOLLY_ARM == 1;
102 constexpr bool kIsArchAmd64 = FOLLY_X64 == 1;
103 constexpr bool kIsArchAArch64 = FOLLY_AARCH64 == 1;
104 constexpr bool kIsArchPPC64 = FOLLY_PPC64 == 1;
105 } // namespace folly
106 
107 namespace folly {
108 
109 /**
110  * folly::kIsSanitizeAddress reports if folly was compiled with ASAN
111  * enabled.  Note that for compilation units outside of folly that include
112  * folly/Portability.h, the value of kIsSanitizeAddress may be different
113  * from whether or not the current compilation unit is being compiled with ASAN.
114  */
115 #if FOLLY_ASAN_ENABLED
116 constexpr bool kIsSanitizeAddress = true;
117 #else
118 constexpr bool kIsSanitizeAddress = false;
119 #endif
120 
121 #if FOLLY_SANITIZE_THREAD
122 constexpr bool kIsSanitizeThread = true;
123 #else
124 constexpr bool kIsSanitizeThread = false;
125 #endif
126 
127 #if FOLLY_SANITIZE
128 constexpr bool kIsSanitize = true;
129 #else
130 constexpr bool kIsSanitize = false;
131 #endif
132 } // namespace folly
133 
134 // packing is very ugly in msvc
135 #ifdef _MSC_VER
136 #define FOLLY_PACK_ATTR /**/
137 #define FOLLY_PACK_PUSH __pragma(pack(push, 1))
138 #define FOLLY_PACK_POP __pragma(pack(pop))
139 #elif defined(__clang__) || defined(__GNUC__)
140 #define FOLLY_PACK_ATTR __attribute__((__packed__))
141 #define FOLLY_PACK_PUSH /**/
142 #define FOLLY_PACK_POP /**/
143 #else
144 #define FOLLY_PACK_ATTR /**/
145 #define FOLLY_PACK_PUSH /**/
146 #define FOLLY_PACK_POP /**/
147 #endif
148 
149 // Generalize warning push/pop.
150 #if defined(_MSC_VER)
151 #define FOLLY_PUSH_WARNING __pragma(warning(push))
152 #define FOLLY_POP_WARNING __pragma(warning(pop))
153 // Disable the GCC warnings.
154 #define FOLLY_GNU_DISABLE_WARNING(warningName)
155 #define FOLLY_GCC_DISABLE_WARNING(warningName)
156 #define FOLLY_CLANG_DISABLE_WARNING(warningName)
157 #define FOLLY_MSVC_DISABLE_WARNING(warningNumber) \
158   __pragma(warning(disable : warningNumber))
159 #elif defined(__GNUC__)
160 // Clang & GCC
161 #define FOLLY_PUSH_WARNING _Pragma("GCC diagnostic push")
162 #define FOLLY_POP_WARNING _Pragma("GCC diagnostic pop")
163 #define FOLLY_GNU_DISABLE_WARNING_INTERNAL2(warningName) #warningName
164 #define FOLLY_GNU_DISABLE_WARNING(warningName) \
165   _Pragma(                                     \
166       FOLLY_GNU_DISABLE_WARNING_INTERNAL2(GCC diagnostic ignored warningName))
167 #ifdef __clang__
168 #define FOLLY_CLANG_DISABLE_WARNING(warningName) \
169   FOLLY_GNU_DISABLE_WARNING(warningName)
170 #define FOLLY_GCC_DISABLE_WARNING(warningName)
171 #else
172 #define FOLLY_CLANG_DISABLE_WARNING(warningName)
173 #define FOLLY_GCC_DISABLE_WARNING(warningName) \
174   FOLLY_GNU_DISABLE_WARNING(warningName)
175 #endif
176 #define FOLLY_MSVC_DISABLE_WARNING(warningNumber)
177 #else
178 #define FOLLY_PUSH_WARNING
179 #define FOLLY_POP_WARNING
180 #define FOLLY_GNU_DISABLE_WARNING(warningName)
181 #define FOLLY_GCC_DISABLE_WARNING(warningName)
182 #define FOLLY_CLANG_DISABLE_WARNING(warningName)
183 #define FOLLY_MSVC_DISABLE_WARNING(warningNumber)
184 #endif
185 
186 #ifdef FOLLY_HAVE_SHADOW_LOCAL_WARNINGS
187 #define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS            \
188   FOLLY_GNU_DISABLE_WARNING("-Wshadow-compatible-local") \
189   FOLLY_GNU_DISABLE_WARNING("-Wshadow-local")            \
190   FOLLY_GNU_DISABLE_WARNING("-Wshadow")
191 #else
192 #define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS /* empty */
193 #endif
194 
195 // Globally disable -Wshadow for gcc < 5.
196 #if __GNUC__ == 4 && !__clang__
197 FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS
198 #endif
199 
200 /* Platform specific TLS support
201  * gcc implements __thread
202  * msvc implements __declspec(thread)
203  * the semantics are the same
204  * (but remember __thread has different semantics when using emutls (ex. apple))
205  */
206 #if defined(_MSC_VER)
207 #define FOLLY_TLS __declspec(thread)
208 #elif defined(__GNUC__) || defined(__clang__)
209 #define FOLLY_TLS __thread
210 #else
211 #error cannot define platform specific thread local storage
212 #endif
213 
214 #if FOLLY_MOBILE
215 #undef FOLLY_TLS
216 #endif
217 
218 // It turns out that GNU libstdc++ and LLVM libc++ differ on how they implement
219 // the 'std' namespace; the latter uses inline namespaces. Wrap this decision
220 // up in a macro to make forward-declarations easier.
221 #if FOLLY_USE_LIBCPP
222 #include <__config> // @manual
223 #define FOLLY_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD
224 #define FOLLY_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD
225 #else
226 #define FOLLY_NAMESPACE_STD_BEGIN namespace std {
227 #define FOLLY_NAMESPACE_STD_END }
228 #endif
229 
230 // If the new c++ ABI is used, __cxx11 inline namespace needs to be added to
231 // some types, e.g. std::list.
232 #if _GLIBCXX_USE_CXX11_ABI
233 #define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN \
234   inline _GLIBCXX_BEGIN_NAMESPACE_CXX11
235 #define FOLLY_GLIBCXX_NAMESPACE_CXX11_END _GLIBCXX_END_NAMESPACE_CXX11
236 #else
237 #define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN
238 #define FOLLY_GLIBCXX_NAMESPACE_CXX11_END
239 #endif
240 
241 // MSVC specific defines
242 // mainly for posix compat
243 #ifdef _MSC_VER
244 #include <folly/portability/SysTypes.h>
245 
246 // compiler specific to compiler specific
247 // nolint
248 #define __PRETTY_FUNCTION__ __FUNCSIG__
249 
250 // Hide a GCC specific thing that breaks MSVC if left alone.
251 #define __extension__
252 
253 // We have compiler support for the newest of the new, but
254 // MSVC doesn't tell us that.
255 #define __SSE4_2__ 1
256 
257 #endif
258 
259 // Debug
260 namespace folly {
261 #ifdef NDEBUG
262 constexpr auto kIsDebug = false;
263 #else
264 constexpr auto kIsDebug = true;
265 #endif
266 } // namespace folly
267 
268 // Endianness
269 namespace folly {
270 #ifdef _MSC_VER
271 // It's MSVC, so we just have to guess ... and allow an override
272 #ifdef FOLLY_ENDIAN_BE
273 constexpr auto kIsLittleEndian = false;
274 #else
275 constexpr auto kIsLittleEndian = true;
276 #endif
277 #else
278 constexpr auto kIsLittleEndian = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__;
279 #endif
280 constexpr auto kIsBigEndian = !kIsLittleEndian;
281 } // namespace folly
282 
283 #ifndef FOLLY_SSE
284 #if defined(__SSE4_2__)
285 #define FOLLY_SSE 4
286 #define FOLLY_SSE_MINOR 2
287 #elif defined(__SSE4_1__)
288 #define FOLLY_SSE 4
289 #define FOLLY_SSE_MINOR 1
290 #elif defined(__SSE4__)
291 #define FOLLY_SSE 4
292 #define FOLLY_SSE_MINOR 0
293 #elif defined(__SSE3__)
294 #define FOLLY_SSE 3
295 #define FOLLY_SSE_MINOR 0
296 #elif defined(__SSE2__)
297 #define FOLLY_SSE 2
298 #define FOLLY_SSE_MINOR 0
299 #elif defined(__SSE__)
300 #define FOLLY_SSE 1
301 #define FOLLY_SSE_MINOR 0
302 #else
303 #define FOLLY_SSE 0
304 #define FOLLY_SSE_MINOR 0
305 #endif
306 #endif
307 
308 #define FOLLY_SSE_PREREQ(major, minor) \
309   (FOLLY_SSE > major || FOLLY_SSE == major && FOLLY_SSE_MINOR >= minor)
310 
311 #ifndef FOLLY_NEON
312 #if defined(__ARM_NEON) || defined(__ARM_NEON__)
313 #define FOLLY_NEON 1
314 #endif
315 #endif
316 
317 #if FOLLY_UNUSUAL_GFLAGS_NAMESPACE
318 namespace FOLLY_GFLAGS_NAMESPACE {}
319 namespace gflags {
320 using namespace FOLLY_GFLAGS_NAMESPACE;
321 } // namespace gflags
322 #endif
323 
324 // for TARGET_OS_IPHONE
325 #ifdef __APPLE__
326 #include <TargetConditionals.h> // @manual
327 #endif
328 
329 // RTTI may not be enabled for this compilation unit.
330 #if defined(__GXX_RTTI) || defined(__cpp_rtti) || \
331     (defined(_MSC_VER) && defined(_CPPRTTI))
332 #define FOLLY_HAS_RTTI 1
333 #endif
334 
335 #if defined(__APPLE__) || defined(_MSC_VER)
336 #define FOLLY_STATIC_CTOR_PRIORITY_MAX
337 #else
338 // 101 is the highest priority allowed by the init_priority attribute.
339 // This priority is already used by JEMalloc and other memory allocators so
340 // we will take the next one.
341 #define FOLLY_STATIC_CTOR_PRIORITY_MAX __attribute__((__init_priority__(102)))
342 #endif
343 
344 namespace folly {
345 
346 #if __OBJC__
347 constexpr auto kIsObjC = true;
348 #else
349 constexpr auto kIsObjC = false;
350 #endif
351 
352 #if FOLLY_MOBILE
353 constexpr auto kIsMobile = true;
354 #else
355 constexpr auto kIsMobile = false;
356 #endif
357 
358 #if defined(__linux__) && !FOLLY_MOBILE
359 constexpr auto kIsLinux = true;
360 #else
361 constexpr auto kIsLinux = false;
362 #endif
363 
364 #if defined(_WIN32)
365 constexpr auto kIsWindows = true;
366 #else
367 constexpr auto kIsWindows = false;
368 #endif
369 
370 #if __GLIBCXX__
371 constexpr auto kIsGlibcxx = true;
372 #else
373 constexpr auto kIsGlibcxx = false;
374 #endif
375 
376 #if _LIBCPP_VERSION
377 constexpr auto kIsLibcpp = true;
378 #else
379 constexpr auto kIsLibcpp = false;
380 #endif
381 
382 #if FOLLY_USE_LIBSTDCPP
383 constexpr auto kIsLibstdcpp = true;
384 #else
385 constexpr auto kIsLibstdcpp = false;
386 #endif
387 
388 #if _MSC_VER
389 constexpr auto kMscVer = _MSC_VER;
390 #else
391 constexpr auto kMscVer = 0;
392 #endif
393 
394 #if FOLLY_MICROSOFT_ABI_VER
395 constexpr auto kMicrosoftAbiVer = FOLLY_MICROSOFT_ABI_VER;
396 #else
397 constexpr auto kMicrosoftAbiVer = 0;
398 #endif
399 
400 // cpplib is an implementation of the standard library, and is the one typically
401 // used with the msvc compiler
402 #if _CPPLIB_VER
403 constexpr auto kCpplibVer = _CPPLIB_VER;
404 #else
405 constexpr auto kCpplibVer = 0;
406 #endif
407 } // namespace folly
408 
409 // Define FOLLY_USE_CPP14_CONSTEXPR to be true if the compiler's C++14
410 // constexpr support is "good enough".
411 #ifndef FOLLY_USE_CPP14_CONSTEXPR
412 #if defined(__clang__)
413 #define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201300L
414 #elif defined(__GNUC__)
415 #define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201304L
416 #else
417 #define FOLLY_USE_CPP14_CONSTEXPR 0 // MSVC?
418 #endif
419 #endif
420 
421 #if FOLLY_USE_CPP14_CONSTEXPR
422 #define FOLLY_CPP14_CONSTEXPR constexpr
423 #else
424 #define FOLLY_CPP14_CONSTEXPR inline
425 #endif
426 
427 //  MSVC does not permit:
428 //
429 //    extern int const num;
430 //    constexpr int const num = 3;
431 //
432 //  Instead:
433 //
434 //    extern int const num;
435 //    FOLLY_STORAGE_CONSTEXPR int const num = 3;
436 //
437 //  True for MSVC 2015 and MSVC 2017.
438 #if _MSC_VER
439 #define FOLLY_STORAGE_CONSTEXPR
440 #define FOLLY_STORAGE_CPP14_CONSTEXPR
441 #else
442 #if __ICC
443 #define FOLLY_STORAGE_CONSTEXPR
444 #else
445 #define FOLLY_STORAGE_CONSTEXPR constexpr
446 #endif
447 #if FOLLY_USE_CPP14_CONSTEXPR
448 #define FOLLY_STORAGE_CPP14_CONSTEXPR constexpr
449 #else
450 #define FOLLY_STORAGE_CPP14_CONSTEXPR
451 #endif
452 #endif
453 
454 #if __cpp_coroutines >= 201703L && __has_include(<experimental/coroutine>)
455 #define FOLLY_HAS_COROUTINES 1
456 #elif _MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED
457 #define FOLLY_HAS_COROUTINES 1
458 #endif
459 
460 // MSVC 2017.5 && C++17
461 #if __cpp_noexcept_function_type >= 201510 || \
462     (_MSC_FULL_VER >= 191225816 && _MSVC_LANG > 201402)
463 #define FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE 1
464 #endif
465 
466 // Define FOLLY_HAS_EXCEPTIONS
467 #if __cpp_exceptions >= 199711 || FOLLY_HAS_FEATURE(cxx_exceptions)
468 #define FOLLY_HAS_EXCEPTIONS 1
469 #elif __GNUC__
470 #if __EXCEPTIONS
471 #define FOLLY_HAS_EXCEPTIONS 1
472 #else // __EXCEPTIONS
473 #define FOLLY_HAS_EXCEPTIONS 0
474 #endif // __EXCEPTIONS
475 #elif FOLLY_MICROSOFT_ABI_VER
476 #if _CPPUNWIND
477 #define FOLLY_HAS_EXCEPTIONS 1
478 #else // _CPPUNWIND
479 #define FOLLY_HAS_EXCEPTIONS 0
480 #endif // _CPPUNWIND
481 #else
482 #define FOLLY_HAS_EXCEPTIONS 1 // default assumption for unknown platforms
483 #endif
484 
485 // feature test __cpp_lib_string_view is defined in <string>, which is
486 // too heavy to include here.  MSVC __has_include support arrived later
487 // than string_view, so we need an alternate case for it.
488 #ifdef __has_include
489 #if __has_include(<string_view>) && __cplusplus >= 201703L
490 #define FOLLY_HAS_STRING_VIEW 1
491 #else
492 #define FOLLY_HAS_STRING_VIEW 0
493 #endif
494 #else // __has_include
495 #if _MSC_VER >= 1910 && (_MSVC_LANG > 201402 || __cplusplus > 201402)
496 #define FOLLY_HAS_STRING_VIEW 1
497 #else
498 #define FOLLY_HAS_STRING_VIEW 0
499 #endif
500 #endif // __has_include
501