1# C++ Coding Style and Conventions
2
3## General Philosophy
4
5Being an extensive and complicated language, there are often differences of
6opinions on "good" and "bad" C++ code. Bjarne Stroustrup has said "Within C++ is
7a smaller, simpler, safer language struggling to get out." We are striving to
8write in this variant of C++ and are therefore following the "C++ Core
9Guidelines" that Bjarne and Herb Sutter introduced at CppCon 2015.
10
11Beyond a set of rules that help codify "good" and "bad" C++, we have general
12principles that help us align the software we develop with the constraints
13within the problem domain being solved by OpenBMC. These are:
14
151.  Code should be clear and concise.
162.  Code should be written with modern practices.
173.  Code should be performant.
18
19### Code should be clear and concise
20
21> Brevity is the soul of wit.
22
23It is important that code be optimized for the reviewer and maintainer and not
24for the writer. Solutions should avoid tricks that detract from the clarity of
25reviewing and understanding it.
26
27Modern practices allow C++ to be an expressive, but concise, language. We tend
28to favor solutions which succinctly represent the problem in as few lines as
29possible.
30
31When there is a conflict between clarity and conciseness, clarity should win
32out.
33
34### Code should be written with modern practices
35
36We strive to keep our code conforming to and utilizing of the latest in C++
37standards. Today, that means all C++ code should be compiled using C++23
38compiler settings. As the C++26 standard is finalized and compilers support it,
39we will move to it as well.
40
41We also strive to keep the codebase up-to-date with the latest recommended
42practices by the language designers. This is reflected by the choice in
43following the C++ Core Guidelines.
44
45We finally desire to have computers do our thinking for us wherever possible.
46This means having Continuous Integration tests on each repository so that
47regressions are quickly identified prior to merge. It also means having as much
48of this document enforced by tools as possible by, for example, clang-format and
49clang-tidy.
50
51For those coming to the project from pre-C++11 environments we strongly
52recommend the book "Effective Modern C++" as a way to get up to speed on the
53differences between C++98/03 and C++11/14/17/20.
54
55### Code should be performant.
56
57OpenBMC targets embedded processors that typically have 32-64MB of flash and
58similar processing power of a typical smart-watch available in 2016. This means
59that there are times where we must limit library selection and/or coding
60techniques to compensate for this constraint. Due to the current technology,
61performance evaluation is done in order of { code size, cpu utilization, and
62memory size }.
63
64From a macro-optimization perspective, we expect all solutions to have an
65appropriate algorithmic complexity for the problem at hand. Therefore, an
66`O(n^3)` algorithm may be rejected even though it has good clarity when an
67`O(n*lg(n))` solution exists.
68
69## Global Guidelines and Practices
70
71Please follow the guidelines established by the C++ Core Guidelines (CCG).
72
73https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md
74
75[[Last reviewed revision is 53bc78f]]
76
77Exceptions:
78
79### Guideline Support Library (GSL)
80
81We do not currently utilize the Guideline Support Library provided by the CCG.
82Any recommendation within the CCG of GSL conventions may be ignored at this
83time.
84
85### Style recommendations
86
87The following are not followed:
88
89- NL.10 Avoid CamelCase
90- NL.17 Use K&R-derived layout
91
92## Library and Feature Specifics
93
94Additional recommendations within the OpenBMC project on specific language
95features or libraries.
96
97### Exceptions
98
99We do use exceptions as a basis for error handling within OpenBMC.
100
101### Boost
102
103Use of boost is allowed, under the following circumstances:
104
1051. Use is done as a header-only library. This allows unused functions and
106   methods to be removed by the compiler at link time, and avoids adding large
107   amounts of overhead and flash usage.
1082. Implementers should include the lowest level header required to solve the
109   problem at hand. This allows uses to be found and moved forward when new
110   standards are available, as well as reduce compile times, and decrease the
111   possibility of accidental use. (ie, #include <boost/container/flat_map.hpp>
112   not #include <boost/container.hpp>)
1133. The module used should not have an equivalent in the std namespace that meets
114   the same requirements for implementation or clarity: For example, std::chrono
115   should be preferred over boost::chrono. std::array over boost::array.
1164. Use does not conflict with any of the core tenants of this coding standard
117   (clarity, modern practices, or performance).
118
119### iostream
120
121The iostream conventions of using 'operator<<' contribute to an increased code
122size over printf-style operations, due to individual function calls for each
123appended value. We therefore do not use iostreams, or iostream-style APIs, for
124logging.
125
126There are cases when using an iostream utility (such as sstream) can result in
127clearer and similar-sized code. iostream may be used in those situations.
128
129## Coding Style
130
131Indentation, naming practices, etc.
132
133### General
134
135- Line length should be limited to 80 characters.
136- Indentation should be done with 4 space characters.
137- Files should use Unix-style newlines (\n).
138
139### Clang Formatting
140
141Individual OpenBMC repositories can use
142[clang-format](https://clang.llvm.org/docs/ClangFormat.html) if desired. The
143OpenBMC CI infrastructure will automatically verify the code formatting on code
144check-in if a .clang_format file is found within the root directory of the
145repository. This allows for automatic validation of code formatting upon
146check-in.
147
148If a custom configuration is desired, such as using different clang formatting
149for C and C++ files, a format-code.sh script can be created, which can for
150example use different .clang\* files as input depending on the file type. The
151format-code.sh script will be executed as part of CI if found in the root
152directory of the repository, and will check that there are no files that were
153modified after running it (same check as running clang).
154
155OpenBMC requires a clang-format of version 6.0 or greater. An example of how to
156run clang-format against all code in your repo can be found by referencing the
157[tool](https://github.com/openbmc/openbmc-build-scripts/blob/master/scripts/format-code.sh)
158used by CI.
159
160[Example .clang-format](https://www.github.com/openbmc/docs/blob/master/style/cpp/.clang-format)
161
162### Bracket style
163
164- Utilize 'Allman' style brackets. Brackets are on their own line at the same
165  indentation level as the statement that creates the scope.
166
167```
168if (condition)
169{
170    ...
171}
172```
173
174```
175void foo()
176{
177    ...
178}
179```
180
181- Even one line conditional and loop statements should have brackets.
182
183```
184/// Wrong.
185if (condition)
186    do_something;
187
188/// Correct
189if (condition)
190{
191    do_something;
192}
193```
194
195### Indentation
196
197- Content within a namespace should be at the same indentation level as the
198  namespace itself.
199
200```
201namespace foo
202{
203
204content
205
206}
207```
208
209- Content within a class / struct should be indented.
210
211```
212class Foo
213{
214    public:
215        Foo();
216}
217```
218
219- Content within a function / conditional / loop should be indented.
220
221```
222void foo()
223{
224    while (1)
225    {
226        if (bar())
227        {
228            ...
229        }
230    }
231}
232```
233
234- Switch / case statements should be indented.
235
236```
237switch (foo)
238{
239    case bar:
240    {
241        bar();
242        break;
243    }
244
245    case baz:
246    {
247        baz();
248        break;
249    }
250}
251```
252
253- Labels should be indented so they appear at 1 level less than the current
254  indentation, rather than flush to the left. (This is not to say that goto and
255  labels are preferred or should be regularly used, but simply when they are
256  used, this is how they are to be used.)
257
258```
259void foo()
260{
261    if (bar)
262    {
263        do
264        {
265            if (baz)
266            {
267                goto exit;
268            }
269
270        } while(1);
271
272    exit:
273        cleanup();
274    }
275}
276```
277
278### Naming Conventions.
279
280- We generally abstain from any prefix or suffix on names.
281- Acronyms should be same-case throughout and follow the requirements as in
282  their appropriate section.
283
284```
285/// Correct.
286SomeBMCType someBMCVariable = bmcFunction();
287
288/// Wrong: type and variable are mixed-case, function isn't lowerCamelCase.
289SomeBmcType someBmcVariable = BMCFunction();
290```
291
292### Header Ordering
293
294Header inclusion order for a header file:
295
296```
297local headers (e.g. "daemon_sys.hpp")
298c-libraries
299cpp-libraries (including openbmc libraries)
300```
301
302Header inclusion order for a source file:
303
304```
305source.hpp (if applicable)
306local headers
307c-libraries
308cpp-libraries
309```
310
311All in alphabetically sorted order.
312
313#### Files
314
315- C++ headers should end in ".hpp". C headers should end in ".h".
316- C++ files should be named with lower_snake_case.
317
318#### Types
319
320- Prefer 'using' over 'typedef' for type aliases.
321- Structs, classes, enums, and typed template parameters should all be in
322  UpperCamelCase.
323- Prefer namespace scoping rather than long names with prefixes.
324- A single-word type alias within a struct / class may be lowercase to match STL
325  conventions (`using type = T`) while a multi-word type alias should be
326  UpperCamelCase (`using ArrayOfT = std::array<T, N>`).
327- Exception: A library API may use lower_snake_case to match conventions of the
328  STL or an underlying C library it is abstracting. Application APIs should all
329  be UpperCamelCase.
330- Exception: A for-convenience template type alias of a template class may end
331  in `_t` to match the conventions of the STL.
332
333```
334template <typename T>
335class Foo
336{
337    using type = std::decay_t<T>;
338};
339
340template <typename T> using foo_t = Foo<T>::type;
341```
342
343#### Variables
344
345- Variables should all be lowerCamelCase, including class members, with no
346  underscores.
347
348#### Functions
349
350- Functions should all be lowerCamelCase.
351- Exception: A library API may use lower_snake-case to match conventions of the
352  STL or an underlying C library it is abstracting. Application APIs should all
353  be lowerCamelCase.
354
355#### Constants
356
357- Constants and enum members should be named like variables in lowerCamelCase.
358
359#### Namespaces
360
361- Namespaces should be lower_snake_case.
362- Top-level namespace should be named based on the containing repository.
363- Favor a namespace called 'details' or 'internal' to indicate the equivalent of
364  a "private" namespace in a header file and anonymous namespaces in a C++ file.
365
366### Header Guards
367
368Prefer '#pragma once' header guard over '#ifndef'-style.
369
370### Additional Whitespace
371
372- Follow NL.18: Use C++-style declarator layout.
373
374```
375foo(T& bar, const S* baz); /// Correct.
376foo(T &bar, const S *baz); /// Incorrect.
377```
378
379- Follow NL.15: Use spaces sparingly.
380
381- Insert whitespace after a conditional and before parens.
382
383```
384if (...)
385while (...)
386for (...)
387```
388
389- Insert whitespace around binary operators for readability.
390
391```
392foo((a-1)/b,c-2); /// Incorrect.
393foo((a - 1) / b, c - 2); /// Correct.
394```
395
396- Do not insert whitespace around unary operators.
397
398```
399a = * b;  /// Incorrect.
400a = & b;  /// Incorrect.
401a = b -> c;  /// Incorrect.
402if (! a)  /// Incorrect.
403```
404
405- Do not insert whitespace inside parens or between a function call and
406  parameters.
407
408```
409foo(x, y); /// Correct.
410foo ( x , y ); /// Incorrect.
411
412do (...)
413{
414} while(0); /// 'while' here is structured like a function call.
415```
416
417- Prefer line-breaks after operators to show continuation.
418
419```
420if (this1 == that1 &&
421    this2 == that2) /// Correct.
422
423if (this1 == that1
424    && this2 == that2) /// Incorrect.
425```
426
427- Long lines should have continuation start at the same level as the parens or
428  all all items inside the parens should be at a 2-level indent.
429
430```
431reallyLongFunctionCall(foo,
432                       bar,
433                       baz); // Correct.
434
435reallyLongFunctionCall(
436        foo,
437        bar,
438        baz); // Also correct.
439
440reallyLongFunctionCall(
441        foo, bar, baz); // Similarly correct.
442
443reallyLongFunctionCall(foo,
444        bar,
445        baz); // Incorrect.
446```
447
448### Misc Guidelines.
449
450- Always use `size_t` or `ssize_t` for things that are sizes, counts, etc. You
451  need a strong rationale for using a sized type (ex. `uint8_t`) when a size_t
452  will do.
453
454- Use `uint8_t`, `int16_t`, `uint32_t`, `int64_t`, etc. for types where size is
455  important due to interactions with hardware or some externally defined API/ABI
456  (such as a system call or library interface). Do not use them, without good
457  reason, when such interaction is not involved; prefer size_t or int instead.
458