Couchbase Lite C
Couchbase Lite C API
Base.h
Go to the documentation of this file.
1//
2// Base.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_BASE_H
15#define FLEECE_BASE_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// Declares that a parameter must not be NULL. The compiler can sometimes detect violations
61// of this at compile time, if the parameter value is a literal.
62// The Clang Undefined-Behavior Sanitizer will detect all violations at runtime.
63// GCC also has an attribute with this name, but it's incompatible: it can't be applied to a
64// parameter, it has to come after the function and list parameters by number. Oh well.
65#ifdef __clang__
66 #define NONNULL __attribute__((nonnull))
67#else
68 #define NONNULL
69#endif
70
71
72// FLPURE functions are _read-only_. They cannot write to memory (in a way that's detectable),
73// and they cannot access volatile data or do I/O.
74//
75// Calling an FLPURE function twice in a row with the same arguments must return the same result.
76//
77// "Many functions have no effects except the return value, and their return value depends only on
78// the parameters and/or global variables. Such a function can be subject to common subexpression
79// elimination and loop optimization just as an arithmetic operator would be. These functions
80// should be declared with the attribute pure."
81// "The pure attribute prohibits a function from modifying the state of the program that is
82// observable by means other than inspecting the function’s return value. However, functions
83// declared with the pure attribute can safely read any non-volatile objects, and modify the value
84// of objects in a way that does not affect their return value or the observable state of the
85// program." -- GCC manual
86#if defined(__GNUC__) || __has_attribute(__pure__)
87 #define FLPURE __attribute__((__pure__))
88#else
89 #define FLPURE
90#endif
91
92// FLCONST is even stricter than FLPURE. The function cannot access memory at all (except for
93// reading immutable values like constants.) The return value can only depend on the parameters.
94//
95// Calling an FLCONST function with the same arguments must _always_ return the same result.
96//
97// "Calls to functions whose return value is not affected by changes to the observable state of the
98// program and that have no observable effects on such state other than to return a value may lend
99// themselves to optimizations such as common subexpression elimination. Declaring such functions
100// with the const attribute allows GCC to avoid emitting some calls in repeated invocations of the
101// function with the same argument values."
102// "Note that a function that has pointer arguments and examines the data pointed to must not be
103// declared const if the pointed-to data might change between successive invocations of the
104// function.
105// "In general, since a function cannot distinguish data that might change from data that cannot,
106// const functions should never take pointer or, in C++, reference arguments. Likewise, a function
107// that calls a non-const function usually must not be const itself." -- GCC manual
108#if defined(__GNUC__) || __has_attribute(__const__)
109 #define FLCONST __attribute__((__const__))
110#else
111 #define FLCONST
112#endif
113
114
115// `constexpr14` is for uses of `constexpr` that are valid in C++14 but not earlier.
116// In constexpr functions this includes `if`, `for`, `while` statements; or multiple `return`s.
117// The macro expands to `constexpr` in C++14 or later, otherwise to nothing.
118#ifdef __cplusplus
119 #if __cplusplus >= 201400L || _MSVC_LANG >= 201400L
120 #define constexpr14 constexpr
121 #else
122 #define constexpr14
123 #endif
124#endif // __cplusplus
125
126
127// STEPOVER is for trivial little glue functions that are annoying to step into in the debugger
128// on the way to the function you _do_ want to step into. Examples are RefCounted's operator->,
129// or slice constructors. Suppressing debug info for those functions means the debugger
130// will continue through them when stepping in.
131// (It probably also makes the debug-symbol file smaller.)
132#if __has_attribute(nodebug)
133 #define STEPOVER __attribute((nodebug))
134#else
135 #define STEPOVER
136#endif
137
138
139// Note: Code below adapted from libmdbx source code.
140
141// `__optimize` is used by the macros below -- you should probably not use it directly, instead
142// use `__hot` or `__cold`. It applies a specific compiler optimization level to a function,
143// e.g. __optimize("O3") or __optimize("Os"). Has no effect in an unoptimized build.
144#ifndef __optimize
145# if defined(__OPTIMIZE__)
146# if defined(__clang__) && !__has_attribute(__optimize__)
147# define __optimize(ops)
148# elif defined(__GNUC__) || __has_attribute(__optimize__)
149# define __optimize(ops) __attribute__((__optimize__(ops)))
150# else
151# define __optimize(ops)
152# endif
153# else
154# define __optimize(ops)
155# endif
156#endif /* __optimize */
157
158#if defined(__clang__)
159 #define HOTLEVEL "Ofast"
160 #define COLDLEVEL "Oz"
161#else
162 #define HOTLEVEL "O3"
163 #define COLDLEVEL "Os"
164#endif
165
166// `__hot` marks a function as being a hot-spot. Optimizes it for speed and may move it to a common
167// code section for hot functions. Has no effect in an unoptimized build.
168#ifndef __hot
169# if defined(__OPTIMIZE__)
170# if defined(__clang__) && !__has_attribute(__hot__) \
171 && __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__))
172 /* just put frequently used functions in separate section */
173# define __hot __attribute__((__section__("text.hot"))) __optimize(HOTLEVEL)
174# elif defined(__GNUC__) || __has_attribute(__hot__)
175# define __hot __attribute__((__hot__)) __optimize(HOTLEVEL)
176# else
177# define __hot __optimize(HOTLEVEL)
178# endif
179# else
180# define __hot
181# endif
182#endif /* __hot */
183
184// `__cold` marks a function as being rarely used (e.g. error handling.) Optimizes it for size and
185// moves it to a common code section for cold functions. Has no effect in an unoptimized build.
186#ifndef __cold
187# if defined(__OPTIMIZE__)
188# if defined(__clang__) && !__has_attribute(__cold__) \
189 && __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__))
190 /* just put infrequently used functions in separate section */
191# define __cold __attribute__((__section__("text.unlikely"))) __optimize(COLDLEVEL)
192# elif defined(__GNUC__) || __has_attribute(__cold__)
193# define __cold __attribute__((__cold__)) __optimize(COLDLEVEL)
194# else
195# define __cold __optimize(COLDLEVEL)
196# endif
197# else
198# define __cold
199# endif
200#endif /* __cold */
201
202
203#ifndef _MSC_VER
204 #define WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 0
205#endif
206
207
208#else // FLEECE_BASE_H
209#warn "Compiler is not honoring #pragma once"
210#endif