1# C++ in Zircon
2
3A subset of the C++17 language is used in the Zircon tree.  This includes both
4the kernel and userspace code.  C++ is mixed with C (and some assembly) in
5both places.  Some C++ language features are avoided or prohibited.  Use of
6the C++ standard library features is very circumspect.
7
8## Language features
9
10- Not allowed
11  - Exceptions
12  - RTTI and `dynamic_cast`
13  - Operator overloading
14  - Virtual inheritance
15  - Statically constructed objects
16  - Trailing return type syntax
17    - Exception: when necessary for lambdas with otherwise unutterable return types
18  - Initializer lists
19  - `thread_local` in kernel code
20- Allowed
21  - Pure interface inheritance
22  - Lambdas
23  - `constexpr`
24  - `nullptr`
25  - `enum class`es
26  - `template`s
27  - Default parameters
28    - But use judgment. One optional out parameter at the end is
29      probably fine. Four optional bool arguments, probably not.
30  - Plain old classes
31  - `auto`
32  - Multiple implementation inheritance
33    - But be judicious. This is used widely for e.g. intrusive
34    container mixins.
35- Needs more ruling TODO(cpu)
36  - Global constructors
37    - Currently we have these for global data structures.
38
39**TODO:** pointer to style guide(s)?
40
41## C++ Standard Edition (17 vs 14)
42
43Zircon code is built with `-std=c++17` and in general can use C++ 17 language
44and library features freely (subject to style/feature constraints described
45[above](#language-features) and library use guidelines described
46[below](#standard-library)).  There is no *general* concern with staying
47compatible with C++ 14 or earlier versions.  When a standard C++ 17 feature is
48the cleanest way to do something, do it that way.
49
50**However** any library that is **published to the SDK** must be compatible
51with SDK users building in **both** C++ 14 and C++ 17 modes.  So, any
52libraries exported to the SDK must have public header files that are
53*compatible with both `-std=c++14` and `-std=c++17`*.  If a library is
54exported to the SDK as source code rather than as a binary, then its *source
55code must also be completely compatible with both `-std=c++14` and
56`-std=c++17`* (and not require other special options). **TODO(mcgrathr):**
57_pointer to build-system docs about maintaining code to be exported to SDK_
58
59All pure C code (`.c` source files and headers used by them) is C 11.  Some
60special exceptions are made for code meant to be reused by out-of-tree boot
61loaders, which stick to a conservative C 89 subset for embedded code.
62
63## Standard Library
64
65The C++ standard library API has many interfaces of widely varying
66characteristics.  We subdivide the standard library API into several
67categories below, based on the predictability and complexity of each
68particular interface's code generation and use of machine and OS facilities.
69These can be thought of as widening concentric circles of the API from the
70most minimal C-like subset out to the full C++ 17 API.
71
72**NOTE: TODO([ZX-1751](https://fuchsia.atlassian.net/browse/ZX-1751))**
73Currently **Zircon userspace code is restricted to header-only library APIs**
74from the standard C++ library.  This limitation **will be lifted** by
75forthcoming fixes (or overhauls) to the C++ standard library runtime build and
76the build system.  There are no limitations on host-only C++ code.  If you're
77not sure whether an API is header-only, try using it in userspace code in the
78Zircon tree and if you get a link-time error then it's not header-only.
79
80#### Context Matters
81
82This section gives guidelines for how to think about the impact of using a
83particular standard C++ library API on the system as a whole.  There are no
84hard and fast rules, except for the kernel (see the next section)--and except
85for implementation constraints, which one always hopes should be temporary.
86
87The overwhelming rule is **be circumspect**.
88
89 * Consider how well you understand the time and space complexity, the dynamic
90   allocation behavior (if any), and the failure modes of *each API you use*.
91
92 * Then consider the specific *context* where it's being used, and how
93   sensitive that context is to those various kinds of concerns.
94
95 * Be especially wary about **input-dependent** behavior that can quickly
96   become far harder to predict when using nontrivial library facilities.
97
98If you're writing the main I/O logic in a driver, or anything that's in a hot
99path for latency, throughput, or reliability, in any kind of system service,
100then you should be pretty conservative in what library facilities you rely on.
101They're all technically available to you in userspace (though far fewer in the
102kernel; see the next section).  But there's not so many you actually should
103use.  You probably don't want to lean on a lot of `std` containers that do
104fancy dynamic allocation behind the scenes.  They will make it hard for you to
105understand, predict, and control the storage/memory footprint, allocation
106behavior, performance, and reliability of your service.
107
108Nonetheless, even a driver is a userspace program that starts up and parses
109configuration files or arguments and so on.  For all those nonessential or
110start-time functions that are not part of the hot path, using more complex
111library facilities is probably fine when that makes the work easier.  Just
112remember to pay attention to overall metrics for your code, such as
113minimal/total/peak runtime memory use, code bloat (which uses both device
114storage and runtime memory), and resilience to unexpected failure modes.
115Maybe don't double the code size and memory footprint of your driver just to
116leverage that fancy configuration-parsing library.
117
118#### No `std` in kernel
119
120The C++ `std` namespace **cannot** be used in [kernel](../kernel) code, which
121also includes [bootloader](../bootloader).  The few C++ standard library
122headers that don't involve `std::` APIs can still be used directly.  See the
123next section.
124
125No other C++ standard headers should be used in kernel code.  Instead, any
126library facilities worthwhile to have in the kernel (such as `std::move`) will
127be provided via kernel-specific APIs (such as `fbl::move`, perhaps eventually
128in a kernel-specific namespace).  The kernel's implementations of these APIs
129may in fact rely on toolchain headers providing `std::` implementations that
130are aliased to kernel API names.  But only those API implementations and very
131special cases in certain library headers should ever use `std::` in source
132code built into the kernel.
133
134#### Universal headers
135
136These header APIs are safe to use everywhere, even in the kernel.
137
138They include the C++ wrappers on the subset of standard C interfaces that the
139kernel supports:
140
141 * [`<cstdarg>`](https://en.cppreference.com/w/cpp/header/cstdarg)
142 * [`<cstddef>`](https://en.cppreference.com/w/cpp/header/cstddef)
143 * [`<climits>`](https://en.cppreference.com/w/cpp/header/climits)
144 * [`<cstdint>`](https://en.cppreference.com/w/cpp/header/cstdint)
145 * [`<cinttypes>`](https://en.cppreference.com/w/cpp/header/cinttypes)
146 * [`<cassert>`](https://en.cppreference.com/w/cpp/header/cassert)
147 * [`<cstring>`](https://en.cppreference.com/w/cpp/header/cstring)
148
149The `std` namespace aliases for C library APIs from these headers should not
150be used in kernel code.
151
152One pure C++ header is also available even in the kernel:
153
154 * [`<new>`](https://en.cppreference.com/w/cpp/header/new)
155
156   The vanilla non-placement `operator new` and `operator new[]` are not
157   available in the kernel.  Use [`fbl::AllocChecker`
158   `new`](../system/ulib/fbl/include/fbl/alloc_checker.h) instead.
159
160#### Conservative userspace
161
162These header APIs are safe to use everywhere.  They're not allowed in the
163kernel because they're all entirely in the `std` namespace.  But subsets of
164these APIs are likely candidates to get an in-kernel API alias if there is a
165good case for using such an API in kernel code.
166
167These are pure header-only types and templates.  They don't do any dynamic
168allocation of their own.  The time and space complexity of each function
169should be clear from its description.
170
171 * [`<algorithm>`](https://en.cppreference.com/w/cpp/header/algorithm)
172 * [`<array>`](https://en.cppreference.com/w/cpp/header/array)
173 * [`<atomic>`](https://en.cppreference.com/w/cpp/header/atomic)
174 * [`<bitset>`](https://en.cppreference.com/w/cpp/header/bitset)
175 * [`<initializer_list>`](https://en.cppreference.com/w/cpp/header/initializer_list)
176 * [`<iterator>`](https://en.cppreference.com/w/cpp/header/iterator)
177 * [`<limits>`](https://en.cppreference.com/w/cpp/header/limits)
178 * [`<optional>`](https://en.cppreference.com/w/cpp/header/optional)
179 * [`<tuple>`](https://en.cppreference.com/w/cpp/header/tuple)
180 * [`<type_traits>`](https://en.cppreference.com/w/cpp/header/type_traits)
181 * [`<utility>`](https://en.cppreference.com/w/cpp/header/utility)
182 * [`<variant>`](https://en.cppreference.com/w/cpp/header/variant)
183
184These involve some dynamic allocation, but only what's explicit:
185
186 * [`<any>`](https://en.cppreference.com/w/cpp/header/any)
187 * [`<memory>`](https://en.cppreference.com/w/cpp/header/memory)
188
189   The `std::shared_ptr`, `std::weak_ptr`, and `std::auto_ptr` APIs should
190   **never** be used.  Use `std::unique_ptr` and `fbl::RefPtr` instead.
191
192##### Userspace-only
193
194These are not things that would ever be available at all or by any similar API
195or name in the kernel.  But they are generally harmless everywhere in
196userspace.  They do not involve dynamic allocation.
197
198 * Floating-point is never available in kernel code, but can be used
199   (subject to performance considerations) in all userspace code.
200   * [`<cfenv>`](https://en.cppreference.com/w/cpp/header/cfenv)
201   * [`<cfloat>`](https://en.cppreference.com/w/cpp/header/cfloat)
202   * [`<cmath>`](https://en.cppreference.com/w/cpp/header/cmath)
203   * [`<complex>`](https://en.cppreference.com/w/cpp/header/complex)
204   * [`<numeric>`](https://en.cppreference.com/w/cpp/header/numeric)
205   * [`<ratio>`](https://en.cppreference.com/w/cpp/header/ratio)
206   * [`<valarray>`](https://en.cppreference.com/w/cpp/header/valarray)
207
208 * Full C 11 standard library, via C++ wrappers or in standard C `<*.h>`.
209   * [`<csetjmp>`](https://en.cppreference.com/w/cpp/header/csetjmp)
210   * [`<cstdlib>`](https://en.cppreference.com/w/cpp/header/cstdlib)
211   * [Standard C11 interfaces](https://en.cppreference.com/w/c/header)
212
213 * Synchronization and threads.  These standard APIs are safe to use in all
214   userspace code with appropriate discretion.  But it may often be better to
215   use Zircon's own library APIs for similar things, such as
216   [<lib/sync/...>](../system/ulib/sync/include).
217   * [`<condition_variable>`](https://en.cppreference.com/w/cpp/header/condition_variable)
218   * [`<execution>`](https://en.cppreference.com/w/cpp/header/execution)
219   * [`<mutex>`](https://en.cppreference.com/w/cpp/header/mutex)
220   * [`<shared_mutex>`](https://en.cppreference.com/w/cpp/header/shared_mutex)
221   * [`<thread>`](https://en.cppreference.com/w/cpp/header/thread)
222
223#### Kitchen sink
224
225These involve dynamic allocation that is hard to predict and is generally out
226of your control.  The exact runtime behavior and memory requirements are often
227hard to reason about.  Think very hard before using these interfaces in any
228critical path for reliability or performance or in any component that is meant
229to be lean and space-efficient.
230
231 * The entire [Containers library](https://en.cppreference.com/w/cpp/container)
232
233 * [`<functional>`](https://en.cppreference.com/w/cpp/header/functional)
234
235   See [`<lib/fit/function.h>`](../system/ulib/fit/include/lib/fit/function.h)
236   for a homegrown alternative.
237
238 * [`<memory_resource>`](https://en.cppreference.com/w/cpp/header/memory_resource)
239 * [`<scoped_allocator>`](https://en.cppreference.com/w/cpp/header/scoped_allocator)
240
241 * [`<filesystem>`](https://en.cppreference.com/w/cpp/header/filesystem)
242 * [`<regex>`](https://en.cppreference.com/w/cpp/header/regex)
243
244## FBL
245
246FBL is the Fuchsia Base Library, which is shared between kernel and userspace.
247As a result, FBL has very strict dependencies.  For example, FBL cannot depend
248on the syscall interface because the syscall interface is not available within
249the kernel.  Similarly, FBL cannot depend on C library features that are not
250available in the kernel.
251
2521. [system/ulib/fbl](../system/ulib/fbl) which is usable from both
253   kernel and userspace.
2542. [kernel/lib/fbl](../kernel/lib/fbl) which is usable only from
255    the kernel.
256
257**NOTE:** Some FBL interfaces below that overlap with standard C++ library
258interfaces will probably be either removed entirely or made kernel-only (and
259perhaps renamed inside the kernel) once userspace code has migrated to using
260standard C++ library facilities where appropriate.
261
262FBL provides:
263
264- utility code
265  - [basic algorithms](../system/ulib/fbl/include/fbl/algorithm.h)
266  - [integer type limits](../system/ulib/fbl/include/fbl/limits.h)
267  - [type traits](../system/ulib/fbl/include/fbl/type_support.h)
268  - [atomics](../system/ulib/fbl/include/fbl/atomic.h)
269  - [alloc checking new](../system/ulib/fbl/include/fbl/alloc_checker.h)
270- allocators
271  - [slab allocation](../system/ulib/fbl/include/fbl/slab_allocator.h)
272  - [slab malloc](../system/ulib/fbl/include/fbl/slab_malloc.h)
273- arrays
274  - [fixed sized arrays](../system/ulib/fbl/include/fbl/array.h)
275  - [fixed sized arrays](../kernel/lib/fbl/include/fbl/inline_array.h),
276    which stack allocates small arrays
277- inline containers
278  - [doubly linked list](../system/ulib/fbl/include/fbl/intrusive_double_list.h)
279  - [hash table](../system/ulib/fbl/include/fbl/intrusive_hash_table.h)
280  - [singly linked list](../system/ulib/fbl/include/fbl/intrusive_single_list.h)
281  - [wavl trees](../system/ulib/fbl/include/fbl/intrusive_wavl_tree.h)
282- smart pointers
283  - [intrusive refcounted mixin](../system/ulib/fbl/include/fbl/ref_counted.h)
284  - [intrusive refcounting pointer](../system/ulib/fbl/include/fbl/ref_ptr.h)
285  - [unique pointer](../system/ulib/fbl/include/fbl/unique_ptr.h)
286- raii utilities
287  - [auto call](../system/ulib/fbl/include/fbl/auto_call.h) to run
288    code upon leaving scope
289  - [AutoLock](../system/ulib/fbl/include/fbl/auto_lock.h)
290
291FBL has strict controls on memory allocation.  Memory allocation should be
292explicit, using an AllocChecker to let clients recover from allocation
293failures.  In some cases, implicit memory allocation is permitted, but
294functions that implicitly allocate memory must be #ifdef'ed to be unavailable
295in the kernel.
296
297FBL not available outside the Fuchsia Source Tree.
298
299## ZX
300
301ZX contains C++ wrappers for the Zircon [objects](objects) and
302[syscalls](syscalls.md).  These wrappers provide type safety and move semantics
303for handles but offer no opinion beyond what's in syscalls.abigen.  At some
304point in the future, we might autogenerate ZX from syscalls.abigen, similar to
305how we autogenerate the syscall wrappers in other languages.
306
307ZX is part of the Fuchsia SDK.
308
309## FZL
310
311FZL is the Fuchsia Zircon Library.  This library provides value-add for common
312operations involving kernel objects and is free to have opinions about how to
313interact with the Zircon syscalls.  If a piece of code has no dependency on
314Zircon syscalls, the code should go in FBL instead.
315
316FZL not available outside the Fuchsia Source Tree.
317
318## ZXCPP
319
320Some of our code runs in an environment which cannot include the
321standard C++ runtime environment. This environment includes symbols
322like __cxa_pure_virtual that are defined by the ABI and that the
323compiler expects to be ambient. [The zxcpp
324library](../system/ulib/zxcpp) provides that dependency. It also
325includes the placement operator new overloads and, in userspace, the
326standard new and delete operators. Note that it does not include the
327similarly named __cxa_atexit, which in userspace must be provided by
328the libc. See extensive comments in musl's atexit implementation if
329you are curious.
330
331*This library is mutually exclusive of the standard C++ library.*
332
333**NOTE: TODO([ZX-1751](https://fuchsia.atlassian.net/browse/ZX-1751))** The
334ZXCPP library will be removed in favor of hermetic static linking for the
335standard C++ library.  Closed-world C++ modules such as drivers or shared
336libraries with a pure C ABI can use the standard C++ library internally
337without affecting their outward ABIs.  Current users of ZXCPP will become
338users of the hermetic static standard C++ library that link in only the
339minimal ABI symbols that ZXCPP used to provide.
340