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