Couchbase Lite C
Couchbase Lite C API
Loading...
Searching...
No Matches
vendor
couchbase-lite-core
vendor
fleece
API
fleece
CompilerSupport.h
Go to the documentation of this file.
1
//
2
// CompilerSupport.h
3
//
4
// Copyright 2018-Present Couchbase, Inc.
5
//
6
// Use of this software is governed by the Business Source License included
7
// in the file licenses/BSL-Couchbase.txt. As of the Change Date specified
8
// in that file, in accordance with the Business Source License, use of this
9
// software will be governed by the Apache License, Version 2.0, included in
10
// the file licenses/APL2.txt.
11
//
12
13
#pragma once
14
#ifndef _FLEECE_COMPILER_SUPPORT_H
15
#define _FLEECE_COMPILER_SUPPORT_H
16
17
#ifdef __APPLE__
18
#include <sys/cdefs.h>
// include this first to avoid conflict with our definition of __printflike
19
#endif
20
21
22
// The __has_xxx() macros are supported by [at least] Clang and GCC.
23
// Define them to return 0 on other compilers.
24
// https://clang.llvm.org/docs/AttributeReference.html
25
// https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
26
27
#ifndef __has_attribute
28
#define __has_attribute(x) 0
29
#endif
30
31
#ifndef __has_cpp_attribute
32
#define __has_cpp_attribute(x) 0
33
#endif
34
35
#ifndef __has_builtin
36
#define __has_builtin(x) 0
37
#endif
38
39
#ifndef __has_feature
40
#define __has_feature(x) 0
41
#endif
42
43
#ifndef __has_extension
44
#define __has_extension(x) 0
45
#endif
46
47
48
// Tells the optimizer that a function's return value is never NULL.
49
#if __has_attribute(returns_nonnull)
50
# define RETURNS_NONNULL __attribute__((returns_nonnull))
51
#else
52
# define RETURNS_NONNULL
53
#endif
54
55
56
// NODISCARD expands to the C++17/C23 `[[nodiscard]]` attribute.
57
// Use it before a function declaration when it's a mistake to ignore the function's result.
58
#if (__cplusplus >= 201700L) || (__STDC_VERSION__ >= 202000)
59
# define NODISCARD [[nodiscard]]
60
#elif __has_attribute(warn_unused_result)
61
# define NODISCARD __attribute__((warn_unused_result))
62
#else
63
# define NODISCARD
64
#endif
65
66
67
// These have no effect on behavior, but they hint to the optimizer which branch of an 'if'
68
// statement to make faster.
69
// Note: In C++20 the standard attributes `[[likely]]` and `[[unlikely]]` can be used instead,
70
// but they're not syntactically identical.
71
#if __has_builtin(__builtin_expect)
72
#define _usuallyTrue(VAL) __builtin_expect(VAL, true)
73
#define _usuallyFalse(VAL) __builtin_expect(VAL, false)
74
#else
75
#define _usuallyTrue(VAL) (VAL)
76
#define _usuallyFalse(VAL) (VAL)
77
#endif
78
79
80
// Clang nullability annotations, for function parameters and struct fields.
81
// In between FL_ASSUME_NONNULL_BEGIN and FL_ASSUME_NONNULL_END, all pointer declarations implicitly
82
// disallow NULL values, unless annotated with FL_NULLABLE (which must come after the `*`.)
83
// (FL_NONNULL is occasionally necessary when there are multiple levels of pointers.)
84
// NOTE: Only supported in Clang, so far.
85
#if __has_feature(nullability)
86
# define FL_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
87
# define FL_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
88
# define FL_NULLABLE _Nullable
89
# define FL_NONNULL _Nonnull
90
# define FL_RETURNS_NONNULL __attribute__((returns_nonnull))
91
#else
92
# define FL_ASSUME_NONNULL_BEGIN
93
# define FL_ASSUME_NONNULL_END
94
# define FL_NULLABLE
95
# define FL_NONNULL
96
# define FL_RETURNS_NONNULL
97
#endif
98
99
100
// Declares that a parameter must not be NULL. The compiler can sometimes detect violations
101
// of this at compile time, if the parameter value is a literal.
102
// The Clang Undefined-Behavior Sanitizer will detect all violations at runtime.
103
// GCC also has an attribute with this name, but it's incompatible: it can't be applied to a
104
// parameter, it has to come after the function and list parameters by number. Oh well.
105
// TODO: Replace this with the better nullability annotations above.
106
#if defined(__clang__)
107
# define NONNULL __attribute__((nonnull))
108
#else
109
# define NONNULL
110
#endif
111
112
113
// FLPURE functions are _read-only_. They cannot write to memory (in a way that's detectable),
114
// and they cannot access volatile data or do I/O.
115
//
116
// Calling an FLPURE function twice in a row with the same arguments must return the same result.
117
//
118
// "Many functions have no effects except the return value, and their return value depends only on
119
// the parameters and/or global variables. Such a function can be subject to common subexpression
120
// elimination and loop optimization just as an arithmetic operator would be. These functions
121
// should be declared with the attribute pure."
122
// "The pure attribute prohibits a function from modifying the state of the program that is
123
// observable by means other than inspecting the function’s return value. However, functions
124
// declared with the pure attribute can safely read any non-volatile objects, and modify the value
125
// of objects in a way that does not affect their return value or the observable state of the
126
// program." -- GCC manual
127
#if __has_attribute(__pure__)
128
# define FLPURE __attribute__((__pure__))
129
#else
130
# define FLPURE
131
#endif
132
133
// FLCONST is even stricter than FLPURE. The function cannot access memory at all (except for
134
// reading immutable values like constants.) The return value can only depend on the parameters.
135
//
136
// Calling an FLCONST function with the same arguments must _always_ return the same result.
137
//
138
// "Calls to functions whose return value is not affected by changes to the observable state of the
139
// program and that have no observable effects on such state other than to return a value may lend
140
// themselves to optimizations such as common subexpression elimination. Declaring such functions
141
// with the const attribute allows GCC to avoid emitting some calls in repeated invocations of the
142
// function with the same argument values."
143
// "Note that a function that has pointer arguments and examines the data pointed to must not be
144
// declared const if the pointed-to data might change between successive invocations of the
145
// function.
146
// "In general, since a function cannot distinguish data that might change from data that cannot,
147
// const functions should never take pointer or, in C++, reference arguments. Likewise, a function
148
// that calls a non-const function usually must not be const itself." -- GCC manual
149
#if __has_attribute(__const__)
150
# define FLCONST __attribute__((__const__))
151
#else
152
# define FLCONST
153
#endif
154
155
156
// STEPOVER is for trivial little glue functions that are annoying to step into in the debugger
157
// on the way to the function you _do_ want to step into. Examples are RefCounted's operator->,
158
// or slice constructors. Suppressing debug info for those functions means the debugger
159
// will continue through them when stepping in.
160
// (It probably also makes the debug-symbol file smaller.)
161
#if __has_attribute(nodebug)
162
#define STEPOVER __attribute((nodebug))
163
#else
164
#define STEPOVER
165
#endif
166
167
168
// Note: Code below adapted from libmdbx source code.
169
170
// `__optimize` is used by the macros below -- you should probably not use it directly, instead
171
// use `__hot` or `__cold`. It applies a specific compiler optimization level to a function,
172
// e.g. __optimize("O3") or __optimize("Os"). Has no effect in an unoptimized build.
173
#ifndef __optimize
174
# if defined(__OPTIMIZE__)
175
# if defined(__clang__) && !__has_attribute(__optimize__)
176
# define __optimize(ops)
177
# elif defined(__GNUC__) || __has_attribute(__optimize__)
178
# define __optimize(ops) __attribute__((__optimize__(ops)))
179
# else
180
# define __optimize(ops)
181
# endif
182
# else
183
# define __optimize(ops)
184
# endif
185
#endif
/* __optimize */
186
187
#if defined(__clang__)
188
#define HOTLEVEL "Ofast"
189
#define COLDLEVEL "Oz"
190
#else
191
#define HOTLEVEL "O3"
192
#define COLDLEVEL "Os"
193
#endif
194
195
// `__hot` marks a function as being a hot-spot. Optimizes it for speed and may move it to a common
196
// code section for hot functions. Has no effect in an unoptimized build.
197
#ifndef __hot
198
# if defined(__OPTIMIZE__)
199
# if defined(__clang__) && !__has_attribute(__hot__) \
200
&& __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__))
201
/* just put frequently used functions in separate section */
202
# define __hot __attribute__((__section__("text.hot"))) __optimize(HOTLEVEL)
203
# elif defined(__GNUC__) || __has_attribute(__hot__)
204
# define __hot __attribute__((__hot__)) __optimize(HOTLEVEL)
205
# else
206
# define __hot __optimize(HOTLEVEL)
207
# endif
208
# else
209
# define __hot
210
# endif
211
#endif
/* __hot */
212
213
// `__cold` marks a function as being rarely used (e.g. error handling.) Optimizes it for size and
214
// moves it to a common code section for cold functions. Has no effect in an unoptimized build.
215
#ifndef __cold
216
# if defined(__OPTIMIZE__)
217
# if defined(__clang__) && !__has_attribute(__cold__) \
218
&& __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__))
219
/* just put infrequently used functions in separate section */
220
# define __cold __attribute__((__section__("text.unlikely"))) __optimize(COLDLEVEL)
221
# elif defined(__GNUC__) || __has_attribute(__cold__)
222
# define __cold __attribute__((__cold__)) __optimize(COLDLEVEL)
223
# else
224
# define __cold __optimize(COLDLEVEL)
225
# endif
226
# else
227
# define __cold
228
# endif
229
#endif
/* __cold */
230
231
// Declares this function takes a printf-like format string, and the subsequent args should
232
// be type-checked against it.
233
#ifndef __printflike
234
# if __has_attribute(__format__)
235
# define __printflike(fmtarg, firstvararg) \
236
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
237
# else
238
# define __printflike(fmtarg, firstvararg)
239
# endif
240
#endif
241
242
243
// Suppresses sanitizers in a function
244
#ifndef _MSC_VER
245
# define __no_sanitize(X) __attribute__((no_sanitize(X)))
246
#else
247
# define __no_sanitize(X)
248
#endif
249
250
251
#ifndef _MSC_VER
252
#define WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 0
253
#endif
254
255
// On Windows, FLEECE_PUBLIC marks symbols as being exported from the shared library.
256
// However, this is not the whole list of things that are exported. The API methods
257
// are exported using a definition list, but it is not possible to correctly include
258
// initialized global variables, so those need to be marked (both in the header and
259
// implementation) with FLEECE_PUBLIC. See kFLNullValue below and in Fleece.cc
260
// for an example.
261
#if defined(_MSC_VER)
262
# ifdef FLEECE_EXPORTS
263
# define FLEECE_PUBLIC __declspec(dllexport)
264
# else
265
# define FLEECE_PUBLIC __declspec(dllimport)
266
# endif
267
# define FLEECE_PUBLIC_IMPL FLEECE_PUBLIC
268
#else
269
# define FLEECE_PUBLIC __attribute__((visibility("default")))
270
# ifdef __clang__
271
# define FLEECE_PUBLIC_IMPL FLEECE_PUBLIC
272
# else
273
# define FLEECE_PUBLIC_IMPL
274
# endif
275
#endif
276
277
#ifdef __cplusplus
278
# define FLAPI noexcept
279
280
// `LIFETIMEBOUND` helps Clang detect value lifetime errors, where one value's lifetime is tied to another and the
281
// dependent value is used after the value it depends on exits scope. For examples of usage, see slice.hh.
282
// "The `lifetimebound` attribute on a function parameter or implicit object parameter indicates that objects that are
283
// referred to by that parameter may also be referred to by the return value of the annotated function (or, for a
284
// parameter of a constructor, by the value of the constructed object)."
285
// -- https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
286
# if __has_cpp_attribute(clang::lifetimebound)
287
# define LIFETIMEBOUND [[clang::lifetimebound]]
288
# else
289
# define LIFETIMEBOUND
290
# endif
291
#else
292
# define FLAPI
293
# define LIFETIMEBOUND
294
#endif
295
296
// Type-checking for printf-style vararg functions:
297
#ifndef __printflike
298
# if __has_attribute(__format__)
299
# define __printflike(fmtarg, firstvararg) __attribute__((__format__(__printf__, fmtarg, firstvararg)))
300
# else
301
# define __printflike(A, B)
302
# endif
303
#endif
304
305
306
#else
// _FLEECE_COMPILER_SUPPORT_H
307
#warn "Compiler is not honoring #pragma once"
308
#endif
Generated by
1.14.0