Couchbase Lite C
Couchbase Lite C API
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
// The __has_xxx() macros are supported by [at least] Clang and GCC.
18
// Define them to return 0 on other compilers.
19
// https://clang.llvm.org/docs/AttributeReference.html
20
// https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
21
22
#ifndef __has_attribute
23
#define __has_attribute(x) 0
24
#endif
25
26
#ifndef __has_builtin
27
#define __has_builtin(x) 0
28
#endif
29
30
#ifndef __has_feature
31
#define __has_feature(x) 0
32
#endif
33
34
#ifndef __has_extension
35
#define __has_extension(x) 0
36
#endif
37
38
39
// Tells the optimizer that a function's return value is never NULL.
40
#if __has_attribute(returns_nonnull)
41
# define RETURNS_NONNULL __attribute__((returns_nonnull))
42
#else
43
# define RETURNS_NONNULL
44
#endif
45
46
// deprecated; use NODISCARD instead
47
#if __has_attribute(returns_nonnull)
48
# define MUST_USE_RESULT __attribute__((warn_unused_result))
49
#else
50
# define MUST_USE_RESULT
51
#endif
52
53
// NODISCARD expands to the C++17/C23 `[[nodiscard]]` attribute, or else MUST_USE_RESULT.
54
// (We can't just redefine MUST_USE_RESULT as `[[nodiscard]]` unfortunately, because the former is
55
// already in use in positions where `[[nodiscard]]` isn't valid, like at the end of a declaration.)
56
#if (__cplusplus >= 201700L) || (__STDC_VERSION__ >= 202000)
57
# define NODISCARD [[nodiscard]]
58
#else
59
# define NODISCARD MUST_USE_RESULT
60
#endif
61
62
// These have no effect on behavior, but they hint to the optimizer which branch of an 'if'
63
// statement to make faster.
64
#if __has_builtin(__builtin_expect)
65
#define _usuallyTrue(VAL) __builtin_expect(VAL, true)
66
#define _usuallyFalse(VAL) __builtin_expect(VAL, false)
67
#else
68
#define _usuallyTrue(VAL) (VAL)
69
#define _usuallyFalse(VAL) (VAL)
70
#endif
71
72
73
// Nullability annotations, for function parameters and struct fields.
74
// In between FL_ASSUME_NONNULL_BEGIN and FL_ASSUME_NONNULL_END, all pointer declarations implicitly
75
// disallow NULL values, unless annotated with FL_NULLABLE (which must come after the `*`.)
76
// (FL_NONNULL is occasionally necessary when there are multiple levels of pointers.)
77
// NOTE: Only supported in Clang, so far.
78
#if __has_feature(nullability)
79
# define FL_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin"
)
80
# define FL_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end"
)
81
# define FL_NULLABLE _Nullable
82
# define FL_NONNULL _Nonnull
83
# define FL_RETURNS_NONNULL __attribute__((returns_nonnull))
84
#else
85
# define FL_ASSUME_NONNULL_BEGIN
86
# define FL_ASSUME_NONNULL_END
87
# define FL_NULLABLE
88
# define FL_NONNULL
89
# define FL_RETURNS_NONNULL
90
#endif
91
92
93
// Declares that a parameter must not be NULL. The compiler can sometimes detect violations
94
// of this at compile time, if the parameter value is a literal.
95
// The Clang Undefined-Behavior Sanitizer will detect all violations at runtime.
96
// GCC also has an attribute with this name, but it's incompatible: it can't be applied to a
97
// parameter, it has to come after the function and list parameters by number. Oh well.
98
// TODO: Replace this with the better nullability annotations above.
99
#if __has_attribute(nonnull)
100
# define NONNULL __attribute__((nonnull))
101
#else
102
# define NONNULL
103
#endif
104
105
106
// FLPURE functions are _read-only_. They cannot write to memory (in a way that's detectable),
107
// and they cannot access volatile data or do I/O.
108
//
109
// Calling an FLPURE function twice in a row with the same arguments must return the same result.
110
//
111
// "Many functions have no effects except the return value, and their return value depends only on
112
// the parameters and/or global variables. Such a function can be subject to common subexpression
113
// elimination and loop optimization just as an arithmetic operator would be. These functions
114
// should be declared with the attribute pure."
115
// "The pure attribute prohibits a function from modifying the state of the program that is
116
// observable by means other than inspecting the function’s return value. However, functions
117
// declared with the pure attribute can safely read any non-volatile objects, and modify the value
118
// of objects in a way that does not affect their return value or the observable state of the
119
// program." -- GCC manual
120
#if __has_attribute(__pure__)
121
# define FLPURE __attribute__((__pure__))
122
#else
123
# define FLPURE
124
#endif
125
126
// FLCONST is even stricter than FLPURE. The function cannot access memory at all (except for
127
// reading immutable values like constants.) The return value can only depend on the parameters.
128
//
129
// Calling an FLCONST function with the same arguments must _always_ return the same result.
130
//
131
// "Calls to functions whose return value is not affected by changes to the observable state of the
132
// program and that have no observable effects on such state other than to return a value may lend
133
// themselves to optimizations such as common subexpression elimination. Declaring such functions
134
// with the const attribute allows GCC to avoid emitting some calls in repeated invocations of the
135
// function with the same argument values."
136
// "Note that a function that has pointer arguments and examines the data pointed to must not be
137
// declared const if the pointed-to data might change between successive invocations of the
138
// function.
139
// "In general, since a function cannot distinguish data that might change from data that cannot,
140
// const functions should never take pointer or, in C++, reference arguments. Likewise, a function
141
// that calls a non-const function usually must not be const itself." -- GCC manual
142
#if __has_attribute(__const__)
143
# define FLCONST __attribute__((__const__))
144
#else
145
# define FLCONST
146
#endif
147
148
149
// `constexpr14` is for uses of `constexpr` that are valid in C++14 but not earlier.
150
// In constexpr functions this includes `if`, `for`, `while` statements; or multiple `return`s.
151
// The macro expands to `constexpr` in C++14 or later, otherwise to nothing.
152
#ifdef __cplusplus
153
#if __cplusplus >= 201400L || _MSVC_LANG >= 201400L
154
#define constexpr14 constexpr
155
#else
156
#define constexpr14
157
#endif
158
#endif
// __cplusplus
159
160
161
// STEPOVER is for trivial little glue functions that are annoying to step into in the debugger
162
// on the way to the function you _do_ want to step into. Examples are RefCounted's operator->,
163
// or slice constructors. Suppressing debug info for those functions means the debugger
164
// will continue through them when stepping in.
165
// (It probably also makes the debug-symbol file smaller.)
166
#if __has_attribute(nodebug)
167
#define STEPOVER __attribute((nodebug))
168
#else
169
#define STEPOVER
170
#endif
171
172
173
// Note: Code below adapted from libmdbx source code.
174
175
// `__optimize` is used by the macros below -- you should probably not use it directly, instead
176
// use `__hot` or `__cold`. It applies a specific compiler optimization level to a function,
177
// e.g. __optimize("O3") or __optimize("Os"). Has no effect in an unoptimized build.
178
#ifndef __optimize
179
# if defined(__OPTIMIZE__)
180
# if defined(__clang__) && !__has_attribute(__optimize__)
181
# define __optimize(ops)
182
# elif defined(__GNUC__) || __has_attribute(__optimize__)
183
# define __optimize(ops) __attribute__((__optimize__(ops)))
184
# else
185
# define __optimize(ops)
186
# endif
187
# else
188
# define __optimize(ops)
189
# endif
190
#endif
/* __optimize */
191
192
#if defined(__clang__)
193
#define HOTLEVEL "Ofast"
194
#define COLDLEVEL "Oz"
195
#else
196
#define HOTLEVEL "O3"
197
#define COLDLEVEL "Os"
198
#endif
199
200
// `__hot` marks a function as being a hot-spot. Optimizes it for speed and may move it to a common
201
// code section for hot functions. Has no effect in an unoptimized build.
202
#ifndef __hot
203
# if defined(__OPTIMIZE__)
204
# if defined(__clang__) && !__has_attribute(__hot__) \
205
&& __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__))
206
/* just put frequently used functions in separate section */
207
# define __hot __attribute__((__section__("text.hot"
))) __optimize(HOTLEVEL)
208
# elif defined(__GNUC__) || __has_attribute(__hot__)
209
# define __hot __attribute__((__hot__)) __optimize(HOTLEVEL)
210
# else
211
# define __hot __optimize(HOTLEVEL)
212
# endif
213
# else
214
# define __hot
215
# endif
216
#endif
/* __hot */
217
218
// `__cold` marks a function as being rarely used (e.g. error handling.) Optimizes it for size and
219
// moves it to a common code section for cold functions. Has no effect in an unoptimized build.
220
#ifndef __cold
221
# if defined(__OPTIMIZE__)
222
# if defined(__clang__) && !__has_attribute(__cold__) \
223
&& __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__))
224
/* just put infrequently used functions in separate section */
225
# define __cold __attribute__((__section__("text.unlikely"
))) __optimize(COLDLEVEL)
226
# elif defined(__GNUC__) || __has_attribute(__cold__)
227
# define __cold __attribute__((__cold__)) __optimize(COLDLEVEL)
228
# else
229
# define __cold __optimize(COLDLEVEL)
230
# endif
231
# else
232
# define __cold
233
# endif
234
#endif
/* __cold */
235
236
237
#ifndef _MSC_VER
238
#define WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 0
239
#endif
240
241
// On Windows, FLEECE_PUBLIC marks symbols as being exported from the shared library.
242
// However, this is not the whole list of things that are exported. The API methods
243
// are exported using a definition list, but it is not possible to correctly include
244
// initialized global variables, so those need to be marked (both in the header and
245
// implementation) with FLEECE_PUBLIC. See kFLNullValue below and in Fleece.cc
246
// for an example.
247
#if defined(_MSC_VER)
248
#ifdef FLEECE_EXPORTS
249
#define FLEECE_PUBLIC __declspec(dllexport)
250
#else
251
#define FLEECE_PUBLIC __declspec(dllimport)
252
#endif
253
#else
254
#define FLEECE_PUBLIC __attribute__((visibility("default"
)))
255
#endif
256
257
#ifdef __cplusplus
258
#define FLAPI noexcept
259
#else
260
#define FLAPI
261
#endif
262
263
#else
// _FLEECE_COMPILER_SUPPORT_H
264
#warn "Compiler is not honoring #pragma once"
265
#endif
Generated by
1.9.2