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