1.. _language_cpp: 2 3C++ Language Support 4#################### 5 6C++ is a general-purpose object-oriented programming language that is based on 7the C language. 8 9Enabling C++ Support 10******************** 11 12Zephyr supports applications written in both C and C++. However, to use C++ in 13an application you must configure Zephyr to include C++ support by selecting 14the :kconfig:option:`CONFIG_CPP` in the application configuration file. 15 16To enable C++ support, the compiler toolchain must also include a C++ compiler 17and the included compiler must be supported by the Zephyr build system. The 18:ref:`toolchain_zephyr_sdk`, which includes the GNU C++ Compiler (part of GCC), 19is supported by Zephyr, and the features and their availability documented 20here assume the use of the Zephyr SDK. 21 22The default C++ standard level (i.e. the language enforced by the 23compiler flags passed) for Zephyr apps is C++11. Other standards are 24available via kconfig choice, for example 25:kconfig:option:`CONFIG_STD_CPP98`. The oldest standard supported and 26tested in Zephyr is C++98. 27 28When compiling a source file, the build system selects the C++ compiler based 29on the suffix (extension) of the files. Files identified with either a **cpp** 30or a **cxx** suffix are compiled using the C++ compiler. For example, 31:file:`myCplusplusApp.cpp` is compiled using C++. 32 33The C++ standard requires the ``main()`` function to have the return type of 34``int``. Your ``main()`` must be defined as ``int main(void)`` or 35``int main(int, char **)``. To use main with arguments the ``CONFIG_BOOTARGS`` option 36has to be selected. Zephyr ignores the return value from main, so applications 37should not return status information and should, instead, return zero. 38 39.. note:: 40 Do not use C++ for kernel, driver, or system initialization code. 41 42Language Features 43***************** 44 45Zephyr currently provides only a subset of C++ functionality. The following 46features are *not* supported: 47 48* Static global object destruction 49* OS-specific C++ standard library classes (e.g. ``std::thread``, 50 ``std::mutex``) 51 52While not an exhaustive list, support for the following functionality is 53included: 54 55* Inheritance 56* Virtual functions 57* Virtual tables 58* Static global object constructors 59* Dynamic object management with the **new** and **delete** operators 60* Exceptions 61* :abbr:`RTTI (runtime type information)` 62* Standard Template Library (STL) 63 64Static global object constructors are initialized after the drivers are 65initialized but before the application :c:func:`main()` function. Therefore, 66use of C++ is restricted to application code. 67 68In order to make use of the C++ exceptions, the 69:kconfig:option:`CONFIG_CPP_EXCEPTIONS` must be selected in the application 70configuration file. 71 72Zephyr Minimal C++ Library 73************************** 74 75Zephyr minimal C++ library (:file:`lib/cpp/minimal`) provides a minimal subset 76of the C++ standard library and application binary interface (ABI) functions to 77enable basic C++ language support. This includes: 78 79* ``new`` and ``delete`` operators 80* virtual function stub and vtables 81* static global initializers for global constructors 82 83The scope of the minimal C++ library is strictly limited to providing the basic 84C++ language support, and it does not implement any `Standard Template Library 85(STL)`_ classes and functions. For this reason, it is only suitable for use in 86the applications that implement their own (non-standard) class library and do 87not rely on the Standard Template Library (STL) components. 88 89Any application that makes use of the Standard Template Library (STL) 90components, such as ``std::string`` and ``std::vector``, must enable the C++ 91standard library support. 92 93C++ Standard Library 94******************** 95 96The `C++ Standard Library`_ is a collection of classes and functions that are 97part of the ISO C++ standard (``std`` namespace). 98 99Zephyr does not include any C++ standard library implementation in source code 100form. Instead, it allows configuring the build system to link against the 101pre-built C++ standard library included in the C++ compiler toolchain. 102 103To enable C++ standard library, select an applicable toolchain-specific C++ 104standard library type from the :kconfig:option:`CONFIG_LIBCPP_IMPLEMENTATION` 105in the application configuration file. 106 107For instance, when building with the :ref:`toolchain_zephyr_sdk`, the build 108system can be configured to link against the GNU C++ Library (``libstdc++.a``), 109which is a fully featured C++ standard library that provides all features 110required by the ISO C++ standard including the Standard Template Library (STL), 111by selecting :kconfig:option:`CONFIG_GLIBCXX_LIBCPP` in the application 112configuration file. 113 114The following C++ standard libraries are supported by Zephyr: 115 116* GNU C++ Library (:kconfig:option:`CONFIG_GLIBCXX_LIBCPP`) 117* ARC MetaWare C++ Library (:kconfig:option:`CONFIG_ARCMWDT_LIBCPP`) 118 119A Zephyr subsystem that requires the features from the full C++ standard 120library can select, from its config, 121:kconfig:option:`CONFIG_REQUIRES_FULL_LIBCPP`, which automatically selects a 122compatible C++ standard library unless the Kconfig symbol for a specific C++ 123standard library is selected. 124 125Header files and incompatibilities between C and C++ 126**************************************************** 127 128To interact with each other, C and C++ must share code through header 129files: data structures, macros, static functions,... While C and C++ 130have a large overlap, they're different languages with `known 131incompatibilities`_. C is not just a C++ subset. Standard levels (e.g.: 132"C+11") add another level of complexity as new features are often 133inspired by and copied from the other language but many years later and 134with subtle differences. Making things more complex, compilers often 135offer early prototypes of features before they become 136standardized. Standards can have ambiguities interpreted differently by 137different compilers. Compilers can have bugs and these may need 138workarounds. To help with this, many projects restrict themselves to a 139limited number of toolchains. Zephyr does not. 140 141These compatibility issues affect header files dis-proportionally. Not 142just because they have to be compatible between C and C++, but also 143because they end up being compiled in a surprisingly high number of other 144source files due to *indirect* inclusion and the `lack of structure and 145headers organization`_ that is typical in real-world projects. So, header 146files are exposed to a much larger variety of toolchains and project 147configurations. 148Adding more constraints, the Zephyr project has demanding policies 149with respect to code style, compiler warnings, static analyzers and 150standard compliance (e.g.: MISRA). 151 152Put together, all these constraints can make writing header files very 153challenging. The purpose of this section is to document some best "header 154practices" and lessons learned in a Zephyr-specific context. While a lot 155of the information here is not Zephyr-specific, this section is not a 156substitute for knowledge of C/C++ standards, textbooks and other 157references. 158 159Testing 160------- 161 162Fortunately, the Zephyr project has an extensive test and CI 163infrastructure that provides coverage baselines, catches issues early, 164enforces policies and maintains such combinatorial explosions under some 165control. The ``tests/lib/cpp/cxx/`` are very useful in this context 166because their ``testcase.yaml`` configuration lets ``twister`` iterate 167quickly over a range of ``-std`` parameters: ``-std=c++98``, 168``-std=c++11``, etc. 169 170Keep in mind unused macros are not compiled. 171 172Designated initializers 173----------------------- 174 175Initialization macros are common in header files as they help reduce 176boilerplate code. C99 added initialization of ``struct`` and ``union`` 177types by "designated" member names instead of a list of *bare* 178expressions. Some GCC versions support designated initializers even in 179their C90 mode. 180 181When used at a simple level, designated initializers are less 182error-prone, more readable and more flexible. On the other hand, C99 183allowed a surprisingly large and lax set of possibilities: designated 184initializers can be out of order, duplicated, "nested" (``.a.x =``), 185various other braces can be omitted, designated initializers and not can 186be mixed, etc. 187 188Twenty years later, C++20 added designated initializers to C++ but in 189much more restricted way; partly because a C++ ``struct`` is actually a 190``class``. As described in the C++ proposal number P0329 (which compares 191with C) or in any complete C++ reference, a mix is not allowed and 192initializers must be in order (gaps are allowed). 193 194Interestingly, the new restrictions in C++20 can cause ``gcc -std=c++20`` 195to fail to compile code that successfully compiles with 196``gcc -std=c++17``. For example, ``gcc -std=c++17`` and older allow the 197C-style mix of initializers and bare expressions. This fails to compile 198with using ``gcc -std=c++20`` *with the same GCC version*. 199 200Recommendation: to maximize compatibility across different C and C++ 201toolchains and standards, designated initializers in Zephyr header files 202should follow all C++20 rules and restrictions. Non-designated, pre-C99 203initialization offers more compatibility and is also allowed but 204designated initialization is the more readable and preferred code 205style. In any case, both styles must never be mixed in the same 206initializer. 207 208Warning: successful compilation is not the end of the incompatibility 209story. For instance, the *evaluation order* of initializer expressions is 210unspecified in C99! It is the (expected) left-to-right order in 211C++20. Other standard revisions may vary. In doubt, do not rely on 212evaluation order (here and elsewhere). 213 214Anonymous unions 215---------------- 216 217Anonymous unions (a.k.a. "unnamed" unions) seem to have been part of C++ 218from its very beginning. They were not officially added to C until C11. 219As usual, there are differences between C and C++. For instance, C 220supports anonymous unions only as a member of an enclosing ``struct`` or 221``union``, empty lists ``{ }`` have always been allowed in C++ but they 222require C23, etc. 223 224When initializing anonymous members, the expression can be enclosed in 225braces or not. It can be either designated or bare. For maximum 226portability, when initializing *anonymous unions*: 227 228- Do *not* enclose *designated* initializers with braces. This is 229 required by C++20 and above which perceive such braces as mixing bare 230 expressions with (other) designated initializers and fails to compile. 231 232- Do enclose *bare* expressions with braces. This is required by C. 233 Maybe because C is laxer and allows many initialization possibilities 234 and variations, so it may need such braces to disambiguate? Note C 235 does allow omitting most braces in initializer expressions - but not 236 in this particular case of initializing anonymous unions with bare 237 expressions. 238 239Some pre-C11 GCC versions support some form of anonymous unions. They 240unfortunately require enclosing their designated initializers with 241braces which conflicts with this recommendation. This can be solved 242with an ``#ifdef __STDC_VERSION__`` as demonstrated in Zephyr commit 243`c15f029a7108 244<https://github.com/zephyrproject-rtos/zephyr/commit/c15f029a7108>`_ and 245the corresponding code review. 246 247 248.. _`C++ Standard Library`: https://en.wikipedia.org/wiki/C%2B%2B_Standard_Library 249.. _`Standard Template Library (STL)`: https://en.wikipedia.org/wiki/Standard_Template_Library 250.. _`known incompatibilities`: https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B 251.. _`lack of structure and headers organization`: 252 https://github.com/zephyrproject-rtos/zephyr/issues/41543 253.. _`gcc commit [C++ PATCH] P0329R4: Designated Initialization`: 254 https://gcc.gnu.org/pipermail/gcc-patches/2017-November/487584.html 255