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