libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
compile_optimize.h
Go to the documentation of this file.
1// Copyright 2025 owent
2// Copy from https://github.com/owent/atframe_utils/blob/main/include/config/compile_optimize.h
3// and remove all macros start with UTIL_* and rename all macros start with ATFW_UTIL_ to LIBCOPP_UTIL_.
4
5#pragma once
6
7// Import the C++20 feature-test macros
8#ifdef __has_include
9# if __has_include(<version>)
10# include <version>
11# endif
12#elif defined(_MSC_VER) && \
13 ((defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L))
14# if _MSC_VER >= 1922
15# include <version>
16# endif
17#endif
18
19// LIBCOPP_UTIL_HAVE_BUILTIN&LIBCOPP_UTIL_HAVE_FEATURE
20//
21// Checks whether the compiler supports a Clang Feature Checking Macro, and if
22// so, checks whether it supports the provided builtin function "x" where x
23// is one of the functions noted in
24// https://clang.llvm.org/docs/LanguageExtensions.html
25//
26// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check.
27// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html
28#if !defined(LIBCOPP_UTIL_HAVE_BUILTIN)
29# ifdef __has_builtin
30# define LIBCOPP_UTIL_HAVE_BUILTIN(x) __has_builtin(x)
31# else
32# define LIBCOPP_UTIL_HAVE_BUILTIN(x) 0
33# endif
34#endif
35
36#if !defined(LIBCOPP_UTIL_HAVE_FEATURE)
37# ifdef __has_feature
38# define LIBCOPP_UTIL_HAVE_FEATURE(f) __has_feature(f)
39# else
40# define LIBCOPP_UTIL_HAVE_FEATURE(f) 0
41# endif
42#endif
43
44// ================ has feature ================
45// LIBCOPP_UTIL_HAVE_ATTRIBUTE
46//
47// A function-like feature checking macro that is a wrapper around
48// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a
49// nonzero constant integer if the attribute is supported or 0 if not.
50//
51// It evaluates to zero if `__has_attribute` is not defined by the compiler.
52//
53// GCC: https://gcc.gnu.org/gcc-5/changes.html
54// Clang: https://clang.llvm.org/docs/LanguageExtensions.html
55#if !defined(LIBCOPP_UTIL_HAVE_ATTRIBUTE)
56# ifdef __has_attribute
57# define LIBCOPP_UTIL_HAVE_ATTRIBUTE(x) __has_attribute(x)
58# else
59# define LIBCOPP_UTIL_HAVE_ATTRIBUTE(x) 0
60# endif
61#endif
62
63// LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE
64//
65// A function-like feature checking macro that accepts C++11 style attributes.
66// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
67// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
68// find `__has_cpp_attribute`, will evaluate to 0.
69#if !defined(LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE)
70# if defined(__cplusplus) && defined(__has_cpp_attribute)
71// NOTE: requiring __cplusplus above should not be necessary, but
72// works around https://bugs.llvm.org/show_bug.cgi?id=23435.
73# define LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
74# else
75# define LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(x) 0
76# endif
77#endif
78
79// ================ branch prediction information ================
80#if !defined(LIBCOPP_UTIL_LIKELY_IF) && defined(__cplusplus)
81// GCC 9 has likely attribute but do not support declare it at the beginning of statement
82# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
83# if __has_cpp_attribute(likely)
84# define LIBCOPP_UTIL_LIKELY_IF(...) if (__VA_ARGS__) [[likely]]
85# endif
86# endif
87#endif
88#if !defined(LIBCOPP_UTIL_LIKELY_IF) && (defined(__clang__) || defined(__GNUC__))
89# define LIBCOPP_UTIL_LIKELY_IF(...) if (__builtin_expect(!!(__VA_ARGS__), true))
90#endif
91#ifndef LIBCOPP_UTIL_LIKELY_IF
92# define LIBCOPP_UTIL_LIKELY_IF(...) if (__VA_ARGS__)
93#endif
94#if !defined(LIBCOPP_UTIL_LIKELY_CONDITION) && defined(__cplusplus)
95// GCC 9 has likely attribute but do not support declare it at the beginning of statement
96# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
97# if __has_cpp_attribute(likely)
98# define LIBCOPP_UTIL_LIKELY_CONDITION(__C) (__C) [[likely]]
99# endif
100# endif
101#endif
102#if !defined(LIBCOPP_UTIL_LIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__))
103# define LIBCOPP_UTIL_LIKELY_CONDITION(__C) (__builtin_expect(!!(__C), true))
104#endif
105#ifndef LIBCOPP_UTIL_LIKELY_CONDITION
106# define LIBCOPP_UTIL_LIKELY_CONDITION(__C) (__C)
107#endif
108
109#if !defined(LIBCOPP_UTIL_UNLIKELY_IF) && defined(__cplusplus)
110// GCC 9 has likely attribute but do not support declare it at the beginning of statement
111# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
112# if __has_cpp_attribute(likely)
113# define LIBCOPP_UTIL_UNLIKELY_IF(...) if (__VA_ARGS__) [[unlikely]]
114# endif
115# endif
116#endif
117#if !defined(LIBCOPP_UTIL_UNLIKELY_IF) && (defined(__clang__) || defined(__GNUC__))
118# define LIBCOPP_UTIL_UNLIKELY_IF(...) if (__builtin_expect(!!(__VA_ARGS__), false))
119#endif
120#ifndef LIBCOPP_UTIL_UNLIKELY_IF
121# define LIBCOPP_UTIL_UNLIKELY_IF(...) if (__VA_ARGS__)
122#endif
123#if !defined(LIBCOPP_UTIL_UNLIKELY_CONDITION) && defined(__cplusplus)
124// GCC 9 has likely attribute but do not support declare it at the beginning of statement
125# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
126# if __has_cpp_attribute(likely)
127# define LIBCOPP_UTIL_UNLIKELY_CONDITION(__C) (__C) [[unlikely]]
128# endif
129# endif
130#endif
131#if !defined(LIBCOPP_UTIL_UNLIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__))
132# define LIBCOPP_UTIL_UNLIKELY_CONDITION(__C) (__builtin_expect(!!(__C), false))
133#endif
134#ifndef LIBCOPP_UTIL_UNLIKELY_CONDITION
135# define LIBCOPP_UTIL_UNLIKELY_CONDITION(__C) (__C)
136#endif
137
138// ---------------- branch prediction information ----------------
139
140// ================ import/export ================
141// @see https://gcc.gnu.org/wiki/Visibility
142// @see http://releases.llvm.org/9.0.0/tools/clang/docs/AttributeReference.html
143// 不支持 borland/sunpro_cc/xlcpp
144
145// ================ import/export: for compilers ================
146#if defined(__GNUC__) && !defined(__ibmxl__)
147// GNU C++/Clang
148//
149// Dynamic shared object (DSO) and dynamic-link library (DLL) support
150//
151# if __GNUC__ >= 4
152# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
153// All Win32 development environments, including 64-bit Windows and MinGW, define
154// _WIN32 or one of its variant spellings. Note that Cygwin is a POSIX environment,
155// so does not define _WIN32 or its variants.
156# ifndef LIBCOPP_UTIL_SYMBOL_EXPORT
157# define LIBCOPP_UTIL_SYMBOL_EXPORT __attribute__((__dllexport__))
158# endif
159# ifndef LIBCOPP_UTIL_SYMBOL_IMPORT
160# define LIBCOPP_UTIL_SYMBOL_IMPORT __attribute__((__dllimport__))
161# endif
162
163# else
164
165# ifndef LIBCOPP_UTIL_SYMBOL_EXPORT
166# define LIBCOPP_UTIL_SYMBOL_EXPORT __attribute__((visibility("default")))
167# endif
168# ifndef LIBCOPP_UTIL_SYMBOL_IMPORT
169# define LIBCOPP_UTIL_SYMBOL_IMPORT __attribute__((visibility("default")))
170# endif
171# ifndef LIBCOPP_UTIL_SYMBOL_VISIBLE
172# define LIBCOPP_UTIL_SYMBOL_VISIBLE __attribute__((visibility("default")))
173# endif
174# ifndef LIBCOPP_UTIL_SYMBOL_LOCAL
175# define LIBCOPP_UTIL_SYMBOL_LOCAL __attribute__((visibility("hidden")))
176# endif
177
178# endif
179
180# else
181// config/platform/win32.hpp will define LIBCOPP_UTIL_SYMBOL_EXPORT, etc., unless already defined
182# ifndef LIBCOPP_UTIL_SYMBOL_EXPORT
183# define LIBCOPP_UTIL_SYMBOL_EXPORT
184# endif
185
186# ifndef LIBCOPP_UTIL_SYMBOL_IMPORT
187# define LIBCOPP_UTIL_SYMBOL_IMPORT
188# endif
189# ifndef LIBCOPP_UTIL_SYMBOL_VISIBLE
190# define LIBCOPP_UTIL_SYMBOL_VISIBLE
191# endif
192# ifndef LIBCOPP_UTIL_SYMBOL_LOCAL
193# define LIBCOPP_UTIL_SYMBOL_LOCAL
194# endif
195
196# endif
197
198#elif defined(_MSC_VER)
199// Microsoft Visual C++
200//
201// Must remain the last #elif since some other vendors (Metrowerks, for
202// example) also #define _MSC_VER
203#else
204#endif
205// ---------------- import/export: for compilers ----------------
206
207// ================ import/export: for platform ================
208// Default defines for LIBCOPP_UTIL_SYMBOL_EXPORT and LIBCOPP_UTIL_SYMBOL_IMPORT
209// If a compiler doesn't support __declspec(dllexport)/__declspec(dllimport),
210// its boost/config/compiler/ file must define LIBCOPP_UTIL_SYMBOL_EXPORT and
211// LIBCOPP_UTIL_SYMBOL_IMPORT
212#if !defined(LIBCOPP_UTIL_SYMBOL_EXPORT) && \
213 (defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__))
214
215# ifndef LIBCOPP_UTIL_SYMBOL_EXPORT
216# define LIBCOPP_UTIL_SYMBOL_EXPORT __declspec(dllexport)
217# endif
218# ifndef LIBCOPP_UTIL_SYMBOL_IMPORT
219# define LIBCOPP_UTIL_SYMBOL_IMPORT __declspec(dllimport)
220# endif
221#endif
222// ---------------- import/export: for platform ----------------
223
224#ifndef LIBCOPP_UTIL_SYMBOL_EXPORT
225# define LIBCOPP_UTIL_SYMBOL_EXPORT
226#endif
227#ifndef LIBCOPP_UTIL_SYMBOL_IMPORT
228# define LIBCOPP_UTIL_SYMBOL_IMPORT
229#endif
230#ifndef LIBCOPP_UTIL_SYMBOL_VISIBLE
231# define LIBCOPP_UTIL_SYMBOL_VISIBLE
232#endif
233#ifndef LIBCOPP_UTIL_SYMBOL_LOCAL
234# define LIBCOPP_UTIL_SYMBOL_LOCAL
235#endif
236#ifndef LIBCOPP_UTIL_SYMBOL_NONE
237# define LIBCOPP_UTIL_SYMBOL_NONE
238#endif
239
240// ---------------- import/export ----------------
241
242// ================ __cdecl ================
243#if defined(__GNUC__) || defined(__GNUG__)
244# ifndef __cdecl
245// see https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html
246// Intel x86 architecture specific calling conventions
247# ifdef _M_IX86
248# define __cdecl __attribute__((__cdecl__))
249# else
250# define __cdecl
251# endif
252# endif
253#endif
254// ---------------- __cdecl ----------------
255
256// ================ always inline ================
257
258#ifndef LIBCOPP_UTIL_FORCEINLINE
259# if defined(__clang__)
260# if __cplusplus >= 201103L
261# define LIBCOPP_UTIL_FORCEINLINE [[gnu::always_inline]] inline
262# else
263# define LIBCOPP_UTIL_FORCEINLINE __attribute__((always_inline)) inline
264# endif
265# elif defined(__GNUC__) && __GNUC__ > 3
266# if __cplusplus >= 201103L && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408
267# define LIBCOPP_UTIL_FORCEINLINE [[gnu::always_inline]] inline
268# else
269# define LIBCOPP_UTIL_FORCEINLINE __attribute__((always_inline)) inline
270# endif
271# elif defined(_MSC_VER)
272# define LIBCOPP_UTIL_FORCEINLINE __forceinline
273# else
274# define LIBCOPP_UTIL_FORCEINLINE inline
275# endif
276#endif
277
278#ifndef LIBCOPP_UTIL_NOINLINE_NOCLONE
279# if defined(__clang__)
280# if __cplusplus >= 201103L
281# define LIBCOPP_UTIL_NOINLINE_NOCLONE [[gnu::noinline]]
282# else
283# define LIBCOPP_UTIL_NOINLINE_NOCLONE __attribute__((noinline))
284# endif
285# elif defined(__GNUC__) && __GNUC__ > 3
286# if __cplusplus >= 201103L && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408
287# define LIBCOPP_UTIL_NOINLINE_NOCLONE [[gnu::noinline, gnu::noclone]]
288# else
289# define LIBCOPP_UTIL_NOINLINE_NOCLONE __attribute__((noinline, noclone))
290# endif
291# elif defined(_MSC_VER)
292# define LIBCOPP_UTIL_NOINLINE_NOCLONE __declspec(noinline)
293# else
294# define LIBCOPP_UTIL_NOINLINE_NOCLONE
295# endif
296#endif
297
298#ifndef LIBCOPP_UTIL_CONST_INIT
299# if defined(__cpp_constinit) && __cpp_constinit >= 201907L
300# if defined(_MSC_VER)
301# define LIBCOPP_UTIL_CONST_INIT
302# else
303# define LIBCOPP_UTIL_CONST_INIT constinit
304# endif
305# elif LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
306# define LIBCOPP_UTIL_CONST_INIT [[clang::require_constant_initialization]]
307# else
308# define LIBCOPP_UTIL_CONST_INIT
309# endif
310#endif
311
312// LIBCOPP_UTIL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
313// parameter or implicit object parameter is retained by the return value of the
314// annotated function (or, for a parameter of a constructor, in the value of the
315// constructed object). This attribute causes warnings to be produced if a
316// temporary object does not live long enough.
317//
318// When applied to a reference parameter, the referenced object is assumed to be
319// retained by the return value of the function. When applied to a non-reference
320// parameter (for example, a pointer or a class type), all temporaries
321// referenced by the parameter are assumed to be retained by the return value of
322// the function.
323//
324// See also the upstream documentation:
325// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
326#ifndef LIBCOPP_UTIL_ATTRIBUTE_LIFETIME_BOUND
327# if LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)
328# define LIBCOPP_UTIL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
329# elif LIBCOPP_UTIL_HAVE_ATTRIBUTE(lifetimebound)
330# define LIBCOPP_UTIL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
331# else
332# define LIBCOPP_UTIL_ATTRIBUTE_LIFETIME_BOUND
333# endif
334#endif
335
336// Internal attribute; name and documentation TBD.
337//
338// See the upstream documentation:
339// https://clang.llvm.org/docs/AttributeReference.html#lifetime_capture_by
340#ifndef LIBCOPP_UTIL_INTERNAL_ATTRIBUTE_CAPTURED_BY
341# if LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(clang::lifetime_capture_by)
342# define LIBCOPP_UTIL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) [[clang::lifetime_capture_by(Owner)]]
343# else
344# define LIBCOPP_UTIL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner)
345# endif
346#endif
347
348// LIBCOPP_UTIL_ATTRIBUTE_VIEW indicates that a type is solely a "view" of data that it
349// points to, similarly to a span, string_view, or other non-owning reference
350// type.
351// This enables diagnosing certain lifetime issues similar to those enabled by
352// LIBCOPP_UTIL_ATTRIBUTE_LIFETIME_BOUND, such as:
353//
354// struct LIBCOPP_UTIL_ATTRIBUTE_VIEW StringView {
355// template<class R>
356// StringView(const R&);
357// };
358//
359// StringView f(std::string s) {
360// return s; // warning: address of stack memory returned
361// }
362//
363//
364// See the following links for details:
365// https://reviews.llvm.org/D64448
366// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
367#ifndef LIBCOPP_UTIL_ATTRIBUTE_VIEW
368# if LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && (!defined(__clang_major__) || __clang_major__ >= 13)
369# define LIBCOPP_UTIL_ATTRIBUTE_VIEW [[gsl::Pointer]]
370# else
371# define LIBCOPP_UTIL_ATTRIBUTE_VIEW
372# endif
373#endif
374
375// LIBCOPP_UTIL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or
376// similar class that owns all the data that it points to.
377// This enables diagnosing certain lifetime issues similar to those enabled by
378// LIBCOPP_UTIL_ATTRIBUTE_LIFETIME_BOUND, such as:
379//
380// struct LIBCOPP_UTIL_ATTRIBUTE_VIEW StringView {
381// template<class R>
382// StringView(const R&);
383// };
384//
385// struct LIBCOPP_UTIL_ATTRIBUTE_OWNER String {};
386//
387// StringView f(String s) {
388// return s; // warning: address of stack memory returned
389// }
390//
391//
392// See the following links for details:
393// https://reviews.llvm.org/D64448
394// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
395#ifndef LIBCOPP_UTIL_ATTRIBUTE_OWNER
396# if LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && (!defined(__clang_major__) || __clang_major__ >= 13)
397# define LIBCOPP_UTIL_ATTRIBUTE_OWNER [[gsl::Owner]]
398# else
399# define LIBCOPP_UTIL_ATTRIBUTE_OWNER
400# endif
401#endif
402
403// LIBCOPP_UTIL_ATTRIBUTE_NO_UNIQUE_ADDRESS
404//
405// Indicates a data member can be optimized to occupy no space (if it is empty)
406// and/or its tail padding can be used for other members.
407//
408// For code that is assured to only build with C++20 or later, prefer using
409// the standard attribute `[[no_unique_address]]` directly instead of this
410// macro.
411//
412// https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c20-no_unique_address
413// Current versions of MSVC have disabled `[[no_unique_address]]` since it
414// breaks ABI compatibility, but offers `[[msvc::no_unique_address]]` for
415// situations when it can be assured that it is desired. Since Abseil does not
416// claim ABI compatibility in mixed builds, we can offer it unconditionally.
417#ifndef LIBCOPP_UTIL_ATTRIBUTE_NO_UNIQUE_ADDRESS
418# if defined(_MSC_VER) && _MSC_VER >= 1929
419# define LIBCOPP_UTIL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
420# elif LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(no_unique_address)
421# define LIBCOPP_UTIL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]]
422# else
423# define LIBCOPP_UTIL_ATTRIBUTE_NO_UNIQUE_ADDRESS
424# endif
425#endif
426
427// LIBCOPP_UTIL_ATTRIBUTE_UNINITIALIZED
428//
429// GCC and Clang support a flag `-ftrivial-auto-var-init=<option>` (<option>
430// can be "zero" or "pattern") that can be used to initialize automatic stack
431// variables. Variables with this attribute will be left uninitialized,
432// overriding the compiler flag.
433//
434// See https://clang.llvm.org/docs/AttributeReference.html#uninitialized
435// and https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-uninitialized-variable-attribute
436#ifndef LIBCOPP_UTIL_ATTRIBUTE_UNINITIALIZED
437# if LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(clang::uninitialized)
438# define LIBCOPP_UTIL_ATTRIBUTE_UNINITIALIZED [[clang::uninitialized]]
439# elif LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(gnu::uninitialized)
440# define LIBCOPP_UTIL_ATTRIBUTE_UNINITIALIZED [[gnu::uninitialized]]
441# elif LIBCOPP_UTIL_HAVE_ATTRIBUTE(uninitialized)
442# define LIBCOPP_UTIL_ATTRIBUTE_UNINITIALIZED __attribute__((uninitialized))
443# else
444# define LIBCOPP_UTIL_ATTRIBUTE_UNINITIALIZED
445# endif
446#endif
447
448// LIBCOPP_UTIL_ATTRIBUTE_WARN_UNUSED
449//
450// Compilers routinely warn about trivial variables that are unused. For
451// non-trivial types, this warning is suppressed since the
452// constructor/destructor may be intentional and load-bearing, for example, with
453// a RAII scoped lock.
454//
455// For example:
456//
457// class LIBCOPP_UTIL_ATTRIBUTE_WARN_UNUSED MyType {
458// public:
459// MyType();
460// ~MyType();
461// };
462//
463// void foo() {
464// // Warns with LIBCOPP_UTIL_ATTRIBUTE_WARN_UNUSED attribute present.
465// MyType unused;
466// }
467//
468// See https://clang.llvm.org/docs/AttributeReference.html#warn-unused and
469// https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#index-warn_005funused-type-attribute
470#ifndef LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE
471# if LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(gnu::warn_unused)
472# define LIBCOPP_UTIL_ATTRIBUTE_WARN_UNUSED [[gnu::warn_unused]]
473# else
474# define LIBCOPP_UTIL_ATTRIBUTE_WARN_UNUSED
475# endif
476#endif
477
478// LIBCOPP_UTIL_HAVE_MEMORY_SANITIZER
479//
480// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of
481// a compiler instrumentation module and a run-time library.
482#ifndef LIBCOPP_UTIL_HAVE_MEMORY_SANITIZER
483# if !defined(__native_client__) && LIBCOPP_UTIL_HAVE_FEATURE(memory_sanitizer)
484# define LIBCOPP_UTIL_HAVE_MEMORY_SANITIZER 1
485# else
486# define LIBCOPP_UTIL_HAVE_MEMORY_SANITIZER 0
487# endif
488#endif
489
490#if LIBCOPP_UTIL_HAVE_MEMORY_SANITIZER && LIBCOPP_UTIL_HAVE_ATTRIBUTE(no_sanitize_memory)
491# define LIBCOPP_UTIL_SANITIZER_NO_MEMORY \
492 __attribute__((no_sanitize_memory)) // __attribute__((no_sanitize("memory")))
493#else
494# define LIBCOPP_UTIL_SANITIZER_NO_MEMORY
495#endif
496
497// LIBCOPP_UTIL_HAVE_THREAD_SANITIZER
498//
499// ThreadSanitizer (TSan) is a fast data race detector.
500#ifndef LIBCOPP_UTIL_HAVE_THREAD_SANITIZER
501# if defined(__SANITIZE_THREAD__)
502# define LIBCOPP_UTIL_HAVE_THREAD_SANITIZER 1
503# elif LIBCOPP_UTIL_HAVE_FEATURE(thread_sanitizer)
504# define LIBCOPP_UTIL_HAVE_THREAD_SANITIZER 1
505# else
506# define LIBCOPP_UTIL_HAVE_THREAD_SANITIZER 0
507# endif
508#endif
509
510#if LIBCOPP_UTIL_HAVE_THREAD_SANITIZER && LIBCOPP_UTIL_HAVE_ATTRIBUTE(no_sanitize_thread)
511# define LIBCOPP_UTIL_SANITIZER_NO_THREAD \
512 __attribute__((no_sanitize_thread)) // __attribute__((no_sanitize("thread")))
513#else
514# define LIBCOPP_UTIL_SANITIZER_NO_THREAD
515#endif
516
517// LIBCOPP_UTIL_HAVE_ADDRESS_SANITIZER
518//
519// AddressSanitizer (ASan) is a fast memory error detector.
520#ifndef LIBCOPP_UTIL_HAVE_ADDRESS_SANITIZER
521# if defined(__SANITIZE_ADDRESS__)
522# define LIBCOPP_UTIL_HAVE_ADDRESS_SANITIZER 1
523# elif LIBCOPP_UTIL_HAVE_FEATURE(address_sanitizer)
524# define LIBCOPP_UTIL_HAVE_ADDRESS_SANITIZER 1
525# else
526# define LIBCOPP_UTIL_HAVE_ADDRESS_SANITIZER 0
527# endif
528#endif
529
530// LIBCOPP_UTIL_HAVE_HWADDRESS_SANITIZER
531//
532// Hardware-Assisted AddressSanitizer (or HWASAN) is even faster than asan
533// memory error detector which can use CPU features like ARM TBI, Intel LAM or
534// AMD UAI.
535#ifndef LIBCOPP_UTIL_HAVE_HWADDRESS_SANITIZER
536# if defined(__SANITIZE_HWADDRESS__)
537# define LIBCOPP_UTIL_HAVE_HWADDRESS_SANITIZER 1
538# elif LIBCOPP_UTIL_HAVE_FEATURE(hwaddress_sanitizer)
539# define LIBCOPP_UTIL_HAVE_HWADDRESS_SANITIZER 1
540# else
541# define LIBCOPP_UTIL_HAVE_HWADDRESS_SANITIZER 0
542# endif
543#endif
544
545#if LIBCOPP_UTIL_HAVE_ADDRESS_SANITIZER && LIBCOPP_UTIL_HAVE_ATTRIBUTE(no_sanitize_address)
546# define LIBCOPP_UTIL_SANITIZER_NO_ADDRESS \
547 __attribute__((no_sanitize_address)) // __attribute__((no_sanitize("address")))
548#elif LIBCOPP_UTIL_HAVE_ADDRESS_SANITIZER && defined(_MSC_VER) && _MSC_VER >= 1928
549# define LIBCOPP_UTIL_SANITIZER_NO_ADDRESS __declspec(no_sanitize_address)
550#elif LIBCOPP_UTIL_HAVE_HWADDRESS_SANITIZER && LIBCOPP_UTIL_HAVE_ATTRIBUTE(no_sanitize)
551# define LIBCOPP_UTIL_SANITIZER_NO_ADDRESS __attribute__((no_sanitize("hwaddress")))
552#else
553# define LIBCOPP_UTIL_SANITIZER_NO_ADDRESS
554#endif
555
556// LIBCOPP_UTIL_HAVE_DATAFLOW_SANITIZER
557//
558// Dataflow Sanitizer (or DFSAN) is a generalised dynamic data flow analysis.
559#ifndef LIBCOPP_UTIL_HAVE_DATAFLOW_SANITIZER
560# if defined(DATAFLOW_SANITIZER)
561// GCC provides no method for detecting the presence of the standalone
562// DataFlowSanitizer (-fsanitize=dataflow), so GCC users of -fsanitize=dataflow
563// should also use -DDATAFLOW_SANITIZER.
564# define LIBCOPP_UTIL_HAVE_DATAFLOW_SANITIZER 1
565# elif LIBCOPP_UTIL_HAVE_FEATURE(dataflow_sanitizer)
566# define LIBCOPP_UTIL_HAVE_DATAFLOW_SANITIZER 1
567# else
568# define LIBCOPP_UTIL_HAVE_DATAFLOW_SANITIZER 0
569# endif
570#endif
571
572// LIBCOPP_UTIL_HAVE_LEAK_SANITIZER
573//
574// LeakSanitizer (or lsan) is a detector of memory leaks.
575// https://clang.llvm.org/docs/LeakSanitizer.html
576// https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer
577//
578// The macro LIBCOPP_UTIL_HAVE_LEAK_SANITIZER can be used to detect at compile-time
579// whether the LeakSanitizer is potentially available. However, just because the
580// LeakSanitizer is available does not mean it is active.
581#ifndef LIBCOPP_UTIL_HAVE_LEAK_SANITIZER
582# if defined(LEAK_SANITIZER)
583// GCC provides no method for detecting the presence of the standalone
584// LeakSanitizer (-fsanitize=leak), so GCC users of -fsanitize=leak should also
585// use -DLEAK_SANITIZER.
586# define LIBCOPP_UTIL_HAVE_LEAK_SANITIZER 1
587// Clang standalone LeakSanitizer (-fsanitize=leak)
588# elif LIBCOPP_UTIL_HAVE_FEATURE(leak_sanitizer)
589# define LIBCOPP_UTIL_HAVE_LEAK_SANITIZER 1
590# elif defined(LIBCOPP_UTIL_HAVE_ADDRESS_SANITIZER)
591// GCC or Clang using the LeakSanitizer integrated into AddressSanitizer.
592# define LIBCOPP_UTIL_HAVE_LEAK_SANITIZER 1
593# else
594# define LIBCOPP_UTIL_HAVE_LEAK_SANITIZER 0
595# endif
596#endif
597
598#ifndef LIBCOPP_UTIL_SANITIZER_NO_UNDEFINED
599# if LIBCOPP_UTIL_HAVE_ATTRIBUTE(no_sanitize_undefined)
600# define LIBCOPP_UTIL_SANITIZER_NO_UNDEFINED __attribute__((no_sanitize_undefined))
601# elif LIBCOPP_UTIL_HAVE_ATTRIBUTE(no_sanitize)
602# define LIBCOPP_UTIL_SANITIZER_NO_UNDEFINED __attribute__((no_sanitize("undefined")))
603# else
604# define LIBCOPP_UTIL_SANITIZER_NO_UNDEFINED
605# endif
606#endif
607
608#ifndef LIBCOPP_UTIL_MACRO_INLINE_VARIABLE
609# if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
610# define LIBCOPP_UTIL_MACRO_INLINE_VARIABLE inline
611# else
612# define LIBCOPP_UTIL_MACRO_INLINE_VARIABLE
613# endif
614#endif
615
616// LIBCOPP_UTIL_ATTRIBUTE_REINITIALIZES
617//
618// Indicates that a member function reinitializes the entire object to a known
619// state, independent of the previous state of the object.
620//
621// The clang-tidy check bugprone-use-after-move allows member functions marked
622// with this attribute to be called on objects that have been moved from;
623// without the attribute, this would result in a use-after-move warning.
624#ifndef LIBCOPP_UTIL_ATTRIBUTE_REINITIALIZES
625# if LIBCOPP_UTIL_HAVE_CPP_ATTRIBUTE(clang::reinitializes)
626# define LIBCOPP_UTIL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
627# else
628# define LIBCOPP_UTIL_ATTRIBUTE_REINITIALIZES
629# endif
630#endif
631
632// LIBCOPP_UTIL_ATTRIBUTE_RETURNS_NONNULL
633//
634// Tells the compiler that a particular function never returns a null pointer.
635#if LIBCOPP_UTIL_HAVE_ATTRIBUTE(returns_nonnull) || \
636 (defined(__GNUC__) && (__GNUC__ > 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && !defined(__clang__))
637# define LIBCOPP_UTIL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
638#else
639# define LIBCOPP_UTIL_ATTRIBUTE_RETURNS_NONNULL
640#endif
641
642// Legacy macros
643#ifndef LIBCOPP_UTIL_ATTRIBUTE_RETURNS_NONNULL
644# define LIBCOPP_UTIL_ATTRIBUTE_RETURNS_NONNULL LIBCOPP_UTIL_ATTRIBUTE_RETURNS_NONNULL
645#endif