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/CPortability.h>
22#include <folly/portability/Config.h>
23
24// Unaligned loads and stores
25namespace folly {
26#if FOLLY_HAVE_UNALIGNED_ACCESS
27constexpr bool kHasUnalignedAccess = true;
28#else
29constexpr 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
100namespace folly {
101constexpr bool kIsArchArm = FOLLY_ARM == 1;
102constexpr bool kIsArchAmd64 = FOLLY_X64 == 1;
103constexpr bool kIsArchAArch64 = FOLLY_AARCH64 == 1;
104constexpr bool kIsArchPPC64 = FOLLY_PPC64 == 1;
105} // namespace folly
106
107namespace 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
116constexpr bool kIsSanitizeAddress = true;
117#else
118constexpr bool kIsSanitizeAddress = false;
119#endif
120
121#if FOLLY_SANITIZE_THREAD
122constexpr bool kIsSanitizeThread = true;
123#else
124constexpr bool kIsSanitizeThread = false;
125#endif
126
127#if FOLLY_SANITIZE
128constexpr bool kIsSanitize = true;
129#else
130constexpr 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__
197FOLLY_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// Define FOLLY_HAS_EXCEPTIONS
260#if __cpp_exceptions >= 199711 || FOLLY_HAS_FEATURE(cxx_exceptions)
261#define FOLLY_HAS_EXCEPTIONS 1
262#elif __GNUC__
263#if __EXCEPTIONS
264#define FOLLY_HAS_EXCEPTIONS 1
265#else // __EXCEPTIONS
266#define FOLLY_HAS_EXCEPTIONS 0
267#endif // __EXCEPTIONS
268#elif FOLLY_MICROSOFT_ABI_VER
269#if _CPPUNWIND
270#define FOLLY_HAS_EXCEPTIONS 1
271#else // _CPPUNWIND
272#define FOLLY_HAS_EXCEPTIONS 0
273#endif // _CPPUNWIND
274#else
275#define FOLLY_HAS_EXCEPTIONS 1 // default assumption for unknown platforms
276#endif
277
278// Debug
279namespace folly {
280#ifdef NDEBUG
281constexpr auto kIsDebug = false;
282#else
283constexpr auto kIsDebug = true;
284#endif
285} // namespace folly
286
287// Exceptions
288namespace folly {
289#if FOLLY_HAS_EXCEPTIONS
290constexpr auto kHasExceptions = true;
291#else
292constexpr auto kHasExceptions = false;
293#endif
294} // namespace folly
295
296// Endianness
297namespace folly {
298#ifdef _MSC_VER
299// It's MSVC, so we just have to guess ... and allow an override
300#ifdef FOLLY_ENDIAN_BE
301constexpr auto kIsLittleEndian = false;
302#else
303constexpr auto kIsLittleEndian = true;
304#endif
305#else
306constexpr auto kIsLittleEndian = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__;
307#endif
308constexpr auto kIsBigEndian = !kIsLittleEndian;
309} // namespace folly
310
311#ifndef FOLLY_SSE
312#if defined(__SSE4_2__)
313#define FOLLY_SSE 4
314#define FOLLY_SSE_MINOR 2
315#elif defined(__SSE4_1__)
316#define FOLLY_SSE 4
317#define FOLLY_SSE_MINOR 1
318#elif defined(__SSE4__)
319#define FOLLY_SSE 4
320#define FOLLY_SSE_MINOR 0
321#elif defined(__SSE3__)
322#define FOLLY_SSE 3
323#define FOLLY_SSE_MINOR 0
324#elif defined(__SSE2__)
325#define FOLLY_SSE 2
326#define FOLLY_SSE_MINOR 0
327#elif defined(__SSE__)
328#define FOLLY_SSE 1
329#define FOLLY_SSE_MINOR 0
330#else
331#define FOLLY_SSE 0
332#define FOLLY_SSE_MINOR 0
333#endif
334#endif
335
336#define FOLLY_SSE_PREREQ(major, minor) \
337 (FOLLY_SSE > major || FOLLY_SSE == major && FOLLY_SSE_MINOR >= minor)
338
339#ifndef FOLLY_NEON
340#if defined(__ARM_NEON) || defined(__ARM_NEON__)
341#define FOLLY_NEON 1
342#endif
343#endif
344
345#if FOLLY_UNUSUAL_GFLAGS_NAMESPACE
346namespace FOLLY_GFLAGS_NAMESPACE {}
347namespace gflags {
348using namespace FOLLY_GFLAGS_NAMESPACE;
349} // namespace gflags
350#endif
351
352// for TARGET_OS_IPHONE
353#ifdef __APPLE__
354#include <TargetConditionals.h> // @manual
355#endif
356
357// RTTI may not be enabled for this compilation unit.
358#if defined(__GXX_RTTI) || defined(__cpp_rtti) || \
359 (defined(_MSC_VER) && defined(_CPPRTTI))
360#define FOLLY_HAS_RTTI 1
361#endif
362
363#if defined(__APPLE__) || defined(_MSC_VER)
364#define FOLLY_STATIC_CTOR_PRIORITY_MAX
365#else
366// 101 is the highest priority allowed by the init_priority attribute.
367// This priority is already used by JEMalloc and other memory allocators so
368// we will take the next one.
369#define FOLLY_STATIC_CTOR_PRIORITY_MAX __attribute__((__init_priority__(102)))
370#endif
371
372namespace folly {
373
374#if __OBJC__
375constexpr auto kIsObjC = true;
376#else
377constexpr auto kIsObjC = false;
378#endif
379
380#if FOLLY_MOBILE
381constexpr auto kIsMobile = true;
382#else
383constexpr auto kIsMobile = false;
384#endif
385
386#if defined(__linux__) && !FOLLY_MOBILE
387constexpr auto kIsLinux = true;
388#else
389constexpr auto kIsLinux = false;
390#endif
391
392#if defined(_WIN32)
393constexpr auto kIsWindows = true;
394#else
395constexpr auto kIsWindows = false;
396#endif
397
398#if __GLIBCXX__
399constexpr auto kIsGlibcxx = true;
400#else
401constexpr auto kIsGlibcxx = false;
402#endif
403
404#if _LIBCPP_VERSION
405constexpr auto kIsLibcpp = true;
406#else
407constexpr auto kIsLibcpp = false;
408#endif
409
410#if FOLLY_USE_LIBSTDCPP
411constexpr auto kIsLibstdcpp = true;
412#else
413constexpr auto kIsLibstdcpp = false;
414#endif
415
416#if _MSC_VER
417constexpr auto kMscVer = _MSC_VER;
418#else
419constexpr auto kMscVer = 0;
420#endif
421
422#if FOLLY_MICROSOFT_ABI_VER
423constexpr auto kMicrosoftAbiVer = FOLLY_MICROSOFT_ABI_VER;
424#else
425constexpr auto kMicrosoftAbiVer = 0;
426#endif
427
428// cpplib is an implementation of the standard library, and is the one typically
429// used with the msvc compiler
430#if _CPPLIB_VER
431constexpr auto kCpplibVer = _CPPLIB_VER;
432#else
433constexpr auto kCpplibVer = 0;
434#endif
435} // namespace folly
436
437// Define FOLLY_USE_CPP14_CONSTEXPR to be true if the compiler's C++14
438// constexpr support is "good enough".
439#ifndef FOLLY_USE_CPP14_CONSTEXPR
440#if defined(__clang__)
441#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201300L
442#elif defined(__GNUC__)
443#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201304L
444#else
445#define FOLLY_USE_CPP14_CONSTEXPR 0 // MSVC?
446#endif
447#endif
448
449#if FOLLY_USE_CPP14_CONSTEXPR
450#define FOLLY_CPP14_CONSTEXPR constexpr
451#else
452#define FOLLY_CPP14_CONSTEXPR inline
453#endif
454
455// MSVC does not permit:
456//
457// extern int const num;
458// constexpr int const num = 3;
459//
460// Instead:
461//
462// extern int const num;
463// FOLLY_STORAGE_CONSTEXPR int const num = 3;
464//
465// True for MSVC 2015 and MSVC 2017.
466#if _MSC_VER
467#define FOLLY_STORAGE_CONSTEXPR
468#define FOLLY_STORAGE_CPP14_CONSTEXPR
469#else
470#if __ICC
471#define FOLLY_STORAGE_CONSTEXPR
472#else
473#define FOLLY_STORAGE_CONSTEXPR constexpr
474#endif
475#if FOLLY_USE_CPP14_CONSTEXPR
476#define FOLLY_STORAGE_CPP14_CONSTEXPR constexpr
477#else
478#define FOLLY_STORAGE_CPP14_CONSTEXPR
479#endif
480#endif
481
482#if __cpp_coroutines >= 201703L && __has_include(<experimental/coroutine>)
483#define FOLLY_HAS_COROUTINES 1
484#elif _MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED
485#define FOLLY_HAS_COROUTINES 1
486#endif
487
488// MSVC 2017.5 && C++17
489#if __cpp_noexcept_function_type >= 201510 || \
490 (_MSC_FULL_VER >= 191225816 && _MSVC_LANG > 201402)
491#define FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE 1
492#endif
493
494// feature test __cpp_lib_string_view is defined in <string>, which is
495// too heavy to include here. MSVC __has_include support arrived later
496// than string_view, so we need an alternate case for it.
497#ifdef __has_include
498#if __has_include(<string_view>) && __cplusplus >= 201703L
499#define FOLLY_HAS_STRING_VIEW 1
500#else
501#define FOLLY_HAS_STRING_VIEW 0
502#endif
503#else // __has_include
504#if _MSC_VER >= 1910 && (_MSVC_LANG > 201402 || __cplusplus > 201402)
505#define FOLLY_HAS_STRING_VIEW 1
506#else
507#define FOLLY_HAS_STRING_VIEW 0
508#endif
509#endif // __has_include
510