libcopp
2.3.1
Toggle main menu visibility
Main Page
Related Pages
Namespaces
Namespace List
Namespace Members
All
_
a
b
c
d
e
f
g
h
i
l
m
n
o
p
r
s
t
u
v
w
x
y
Functions
_
a
c
d
f
g
h
i
m
o
p
r
s
t
w
y
Variables
_
a
b
c
d
e
f
g
h
l
m
o
p
r
s
t
u
w
x
Typedefs
Enumerations
Enumerator
Data Structures
Data Structures
Data Structure Index
Class Hierarchy
Data Fields
All
_
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
r
s
t
u
v
w
x
y
~
Functions
_
a
b
c
d
e
f
g
h
i
k
l
m
n
o
p
r
s
t
u
v
w
x
y
~
Variables
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
r
s
t
u
v
w
Typedefs
_
a
b
c
d
e
f
h
i
j
l
m
n
o
p
r
s
t
u
v
w
Enumerations
Enumerator
e
l
s
u
Related Symbols
_
d
e
i
l
o
r
s
w
Files
File List
Globals
All
_
b
c
e
g
j
l
m
o
p
r
s
t
u
w
Functions
b
c
g
j
m
o
p
r
s
t
Variables
b
c
g
m
s
t
Typedefs
Enumerations
Enumerator
c
e
Macros
_
c
l
m
s
t
u
w
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Pages
Loading...
Searching...
No Matches
include
libcopp
utils
config
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
Generated by
1.9.8