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