|  | --- | 
|  | title: "C and C++ Coding Style Guide" | 
|  | --- | 
|  |  | 
|  | ## Basics | 
|  |  | 
|  | ### Summary | 
|  |  | 
|  | C and C++ are widely used languages for (embedded) software. | 
|  |  | 
|  | Our C and C++ style guide follows the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html), with some exceptions and clarifications. | 
|  |  | 
|  | As with all style guides the intention is to: | 
|  | *   promote consistency across projects | 
|  | *   promote best practices | 
|  | *   increase code sharing and re-use | 
|  |  | 
|  |  | 
|  | ### Terminology Conventions | 
|  |  | 
|  | Unless otherwise noted, the following terminology conventions apply to this | 
|  | style guide: | 
|  |  | 
|  | *   The word ***must*** indicates a mandatory requirement. | 
|  | Similarly, ***do not*** indicates a prohibition. | 
|  | Imperative and declarative statements correspond to ***must***. | 
|  | *   The word ***recommended*** indicates that a certain course of action is preferred or is most suitable. | 
|  | Similarly, ***not recommended*** indicates that a course of action is unsuitable, but not prohibited. | 
|  | There may be reasons to use other options, but the implications and reasons for doing so must be fully understood. | 
|  | *   The word ***may*** indicates a course of action is permitted and optional. | 
|  | *   The word ***can*** indicates a course of action is possible given material, physical, or causal constraints. | 
|  |  | 
|  | ## Shared C and C++ Style Guide | 
|  |  | 
|  | We use the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) for both C and C++ code. | 
|  | The following exceptions and additions to this style guide apply to both C and C++ code. | 
|  |  | 
|  | ### Pointers | 
|  |  | 
|  | ***When declaring pointer types, the asterisk (`*`) should be placed next to the variable name, not the type.*** | 
|  |  | 
|  | Example: | 
|  |  | 
|  | ```c | 
|  | int *ptr; | 
|  | ``` | 
|  |  | 
|  | ### Formatting of loops and conditionals | 
|  |  | 
|  | ***Single-statement blocks are not allowed. All conditions and loops must use braces.*** | 
|  |  | 
|  | Example: | 
|  | ```c | 
|  | if (foo) { | 
|  | do_something(); | 
|  | } | 
|  | ``` | 
|  |  | 
|  | ### Comments | 
|  |  | 
|  | ***Comments should be `// C99-style` for consistency with C++.*** | 
|  |  | 
|  | <!-- To render a backtick in inline code in markdown, you need to double the surrounding backticks. | 
|  | https://daringfireball.net/projects/markdown/syntax#code --> | 
|  | ***Variables mentioned in comments should be delimited with backtick (`` ` ``) characters.*** | 
|  |  | 
|  | Example: | 
|  |  | 
|  | ```c | 
|  | // `ptr` can never be NULL for reasons. | 
|  | ``` | 
|  |  | 
|  | Note also [Public function (API) documentation](#public-function-api-documentation) below. | 
|  |  | 
|  | ### TODO Comments | 
|  | ***TODO comments should be in the format `TODO: message`.*** | 
|  |  | 
|  | ***TODO comments which require more explanation should reference an issue.*** | 
|  |  | 
|  | It is recommended to use fully-qualified issue numbers or URLs when referencing issues or pull requests. | 
|  |  | 
|  | TODO comments should not indicate an assignee of the work. | 
|  |  | 
|  | Example: | 
|  |  | 
|  | ```c | 
|  | // TODO: This algorithm should be rewritten to be more efficient. | 
|  | // (Bug lowrisc/reponame#27) | 
|  | ``` | 
|  |  | 
|  | ### Included files | 
|  |  | 
|  | ***`#include` directives must, with exceptions, be rooted at `$REPO_TOP`.*** | 
|  |  | 
|  | Every `#include` directive must be rooted at the repository base, including files in the same directory. | 
|  | This helps the reader quickly find headers in the repository, without having to worry about local include-search rules. | 
|  |  | 
|  | Example: `my/device/library.c` would start with a directive like the following: | 
|  |  | 
|  | ```c | 
|  | #include "my/device/library.h" | 
|  | ``` | 
|  |  | 
|  | This rule does not apply to generated headers, since they do not yet have a designated location in the source tree, and are instead included from ad-hoc locations. | 
|  | Until these questions are resolved, these includes must be marked as follows: | 
|  | ```c | 
|  | #include "my_generated_file.h"  // Generated. | 
|  | ``` | 
|  | This convention helps readers distinguish which files they should not expect to find in-tree. | 
|  |  | 
|  | The above rules also do not apply to system includes, which should be included by the names dictated by the ISO standard, e.g. `#include <stddef.h>`. | 
|  |  | 
|  | ### Linker Script- and Assembly-Provided Symbols | 
|  |  | 
|  | Some C/C++ programs may need to use symbols that are defined by a linker script or in an external assembly file. | 
|  | Referring to linker script- and assembly-provided symbols can be complex and error-prone, as they don't quite work like C's global variables. | 
|  | We have chosen the following approach based on the examples in [the binutils ld manual](https://sourceware.org/binutils/docs/ld/Source-Code-Reference.html). | 
|  |  | 
|  | If you need to refer to the symbol `_my_linker_symbol`, the correct way to do so is with an incomplete extern char array declaration, as shown below. | 
|  | It is good practice to provide a comment that directs others to where the symbol is actually defined, and whether the symbol should be treated as a memory address or another kind of value. | 
|  | ```c | 
|  | /** | 
|  | * `_my_linker_symbol` is defined in the linker script `sw/device/my_feature.ld`. | 
|  | * | 
|  | * `_my_linker_symbol` is a memory address in RAM. | 
|  | */ | 
|  | extern char _my_linker_symbol[]; | 
|  | ``` | 
|  |  | 
|  | A symbol's value is exposed using its address, and declaring it this way allows you to use the symbol where you need a pointer. | 
|  | ```c | 
|  | char my_buffer[4]; | 
|  | memcpy(my_buffer, _my_linker_symbol, sizeof(my_buffer)); | 
|  | ``` | 
|  |  | 
|  | If the symbol has been defined to a non-address value (usually using `ABSOLUTE()` in a linker script, or `.set` in assembly), you must cast the symbol to obtain its value using `(intptr_t)_my_linker_symbol`. | 
|  | You must not dereference a symbol that has non-address value. | 
|  |  | 
|  | ### Public function (API) documentation | 
|  |  | 
|  | ***It is recommended to document public functions, classes, methods, and data structures in the header file with a Doxygen-style comment.*** | 
|  |  | 
|  | The first line of the comment is the summary, followed by a new line, and an optional longer description. | 
|  | Input arguments and return arguments can be documented with `@param` and `@return` if they are not self-explanatory from the name. | 
|  |  | 
|  | The documentation tool will also render markdown within descriptions, so backticks should be used to get monospaced text. | 
|  | It can also generate references to other named declarations using `#other_function` (for C-style declarations), or `ns::foo` (for C++ declarations). | 
|  |  | 
|  | Example: | 
|  |  | 
|  | ```c | 
|  | /** | 
|  | * Do something amazing | 
|  | * | 
|  | * Create a rainbow and place a unicorn at the bottom of it. `pots_of_gold` | 
|  | * pots of gold will be positioned on the east end of the rainbow. | 
|  | * | 
|  | * Can be recycled with #recycle_rainbow. | 
|  | * | 
|  | * @param pots_of_gold Number of gold pots to place next to the rainbow | 
|  | * @param unicorns Number of unicorns to position on the rainbow | 
|  | * @return 0 if the function was successful, -1 otherwise | 
|  | */ | 
|  | int create_rainbow(int pots_of_gold, int unicorns); | 
|  | ``` | 
|  |  | 
|  | ### Polyglot headers | 
|  |  | 
|  | ***Headers intended to be included from both languages must contain `extern` guards; `#include`s should not be wrapped in `extern "C" {}`.*** | 
|  |  | 
|  | A *polyglot header* is a header file that can be safely included in either a `.c` or `.cc` file. | 
|  | In particular, this means that the file must not depend on any of the places where C and C++ semantics disagree. | 
|  | For example: | 
|  | - `sizeof(struct {})` and `sizeof(true)` are different in C and C++. | 
|  | - Function-scope `static` variables generate lock calls in C++. | 
|  | - Some libc macros, like `static_assert`, may not be present in C++. | 
|  | - Character literals type as `char` in C++ but `int` in C. | 
|  |  | 
|  | Such files must be explictly marked with `extern` guards like the following, starting after the file's `#include`s. | 
|  | ``` | 
|  | #ifdef __cplusplus | 
|  | extern "C" { | 
|  | #endif | 
|  |  | 
|  | // Declarations... | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | }  // extern "C" | 
|  | #endif | 
|  | ``` | 
|  | Moreover, all non-system `#includes` in a polyglot header must also be of other polyglot headers. | 
|  | (In other words, all C system headers may be assumed to be polyglot, even if they lack guards.) | 
|  |  | 
|  | Additionally, it is forbidden to wrap `#include` statements in `extern "C"` in a C++ file. | 
|  | While this does correctly set the ABI for a header implemented in C, that header may contain code that subtly depends on the peculiarities of C. | 
|  |  | 
|  | This last rule is waived for third-party headers, which may be polyglot but not declared in our style. | 
|  |  | 
|  | ### X Macros | 
|  |  | 
|  | In order to avoid repetitive definitions or statements, we allow the use of [X Macros](https://en.wikipedia.org/wiki/X_Macro) in our C and C++ code. | 
|  |  | 
|  | Uses of X Macros should follow the following example, which uses this pattern in a switch definition: | 
|  | ```c | 
|  | int get_field2(int identifier) { | 
|  | switch (identifier) { | 
|  | #define ITEM(id_field, data_field1, data_field2) \ | 
|  | case id_field:                               \ | 
|  | return data_field2; | 
|  | #include "path/to/item.def" | 
|  | default: | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | ``` | 
|  | This example expands to a case statement for each item, which returns the `data_field2` value where the passed in identifier matches `id_field`. | 
|  |  | 
|  | The contents of the X Macro file from this example ("path/to/item.def") should look like: | 
|  | ```c | 
|  |  | 
|  | /** | 
|  | * \def ITEM(id_field, data_field1, data_field2) | 
|  | * | 
|  | * <Documentation about meaning of ITEM fields> | 
|  | */ | 
|  | #ifndef ITEM | 
|  | #error ITEM(id_field, data_field1, data_field2) must be defined | 
|  | #endif | 
|  |  | 
|  | ITEM(fields...) | 
|  | ITEM(fields...) | 
|  |  | 
|  | #undef ITEM | 
|  | ``` | 
|  |  | 
|  | These X Macro files must: | 
|  |  | 
|  | *   Have the extension `.def`. | 
|  | The file's basename should match the X Macro name. | 
|  | This is so we can easily identify that this is an X Macro, which will be used by the preprocessor, and is required at compile-time. | 
|  | *   Document the X Macro and the meaning of its fields. | 
|  | *   Error if the X Macro is not defined. | 
|  | *   Include a sequence of X Macro uses, one per line, omitting following semicolons. | 
|  | Omitting semicolons allows X Macros to be used in either expression or statement position, which is useful. | 
|  | *   Undefine the X Macro name at the end of the file. | 
|  |  | 
|  | X Macro field values should be valid C constant literals. | 
|  | The first field of an X Macro should be the primary identifier, as shown in the example. | 
|  |  | 
|  | X Macros should be kept as simple as possible. | 
|  | X Macro files should endeavour to only define one kind of X Macro, and separate files should be used for other X Macros. | 
|  | If possible, X Macros should only be used in implementation files, and should be avoided in headers. | 
|  |  | 
|  | The code using an X Macro must: | 
|  |  | 
|  | *   Define the X Macro name, including any separators (such as semicolons or commas) within the definition. | 
|  | It is usually clearer if you split the definition over multiple lines. | 
|  | *   Immediately after the definition, include the `.def` file for the X Macro. | 
|  |  | 
|  |  | 
|  |  | 
|  | ## C++ Style Guide {#cxx-style-guide} | 
|  |  | 
|  | ### C++ Version {#cxx-version} | 
|  |  | 
|  | C++ code should target C++14. | 
|  |  | 
|  | ### Aggregate Initializers | 
|  |  | 
|  | ***C++20-style designated initializers are permitted in C++ code, when used with POD types.*** | 
|  |  | 
|  | While we target C++14, both GCC and Clang allow C++20 designated initializers in C++14-mode, as an extension: | 
|  | ``` | 
|  | struct Foo { int a, b; }; | 
|  |  | 
|  | Foo f = { .a = 1, .b = 42, }; | 
|  | ``` | 
|  |  | 
|  | This feature is fairly mature in both compilers, though it varies from the C11 variant in two ways important ways: | 
|  | - It can only be used with structs and unions, not arrays. | 
|  | - Members must be initialized in declaration order. | 
|  |  | 
|  | Because it is especially useful with types declared for C, we allow designatued initializers whenever the type is a plain-old-data type, and: | 
|  | - All members are public. | 
|  | - It has no non-trivial constructors. | 
|  | - It has no `virtual` members. | 
|  |  | 
|  | Furthermore, designated initializers do not play well with type deduction and overload resolution. | 
|  | As such, they are forbidden in the following contexts: | 
|  | - Do not call overloaded functions with a designated initializer: `overloaded({ .foo = 0 })`. | 
|  | Instead, disambiguate with syntax like `T var = { .foo = 0 }; overloaded(var);`. | 
|  | - Do not use designated initializers in any place where they would be used for type defuction. | 
|  | This includes `auto`, such as `auto var = { .foo = 0 };`, and a templated argument in a template function. | 
|  |  | 
|  | It is recommended to only use designated initializers with types which use C-style declarations. | 
|  |  | 
|  | ## C Style Guide | 
|  |  | 
|  | The [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) targets C++, but it can also be used for C code with minor adjustments. | 
|  | Consequently, C++-specific rules don't apply. | 
|  | In addition to the shared C and C++ style guide rules outlined before, the following C-specific rules apply. | 
|  |  | 
|  | ### C Version | 
|  |  | 
|  | ***C code should target C11.*** | 
|  |  | 
|  | The following nonstandard extensions may be used: | 
|  | *   Inline assembly | 
|  | *   Nonstandard attributes | 
|  | *   Compiler builtins | 
|  |  | 
|  | It is recommended that no other nonstandard extensions are used. | 
|  |  | 
|  | Any nonstandard features that are used must be compatible with both GCC and Clang. | 
|  |  | 
|  | ### Function, enum, struct and typedef naming | 
|  |  | 
|  | ***Names of functions, `enum`s, `struct`s, and `typedef`s must be `lower_snake_case`.*** | 
|  |  | 
|  | This rule deviates from the Google C++ style guide to align closer with a typical way of writing C code. | 
|  |  | 
|  | ***All symbols in a particular header must share the same unique prefix.*** | 
|  |  | 
|  | "Prefix" in this case refers to the identifying string of words, and not the specific type/struct/enum/constant/macro-based capitalisation. | 
|  | This rule also deviates from the Google C++ style guide, because C does not have namespaces, so we have to use long names to avoid name clashes. | 
|  | Symbols that have specific, global meaning imparted by an external script or specification may break this rule. | 
|  | For example: | 
|  | ```c | 
|  | // in my_unit.h | 
|  | extern const int kMyUnitMaskValue = 0xFF; | 
|  |  | 
|  | typedef enum { kMyUnitReturnOk } my_unit_return_t; | 
|  |  | 
|  | my_unit_return_t my_unit_init(void); | 
|  | ``` | 
|  |  | 
|  | ***The names of enumeration constants must be prefixed with the name of their respective enumeration type.*** | 
|  |  | 
|  | Again, this is because C does not have namespaces. | 
|  | The exact capitalisation does not need to match, as enumeration type names have a different capitalisation rule to enumeration constants. | 
|  | For example: | 
|  | ```c | 
|  | typedef enum my_wonderful_option { | 
|  | kMyWonderfulOptionEnabled, | 
|  | kMyWonderfulOptionDisabled, | 
|  | kMyWonderfulOptionOnlySometimes | 
|  | } my_wonderful_option_t; | 
|  | ``` | 
|  |  | 
|  | ### C-specific Keywords | 
|  |  | 
|  | C11 introduces a number of undescore-prefixed keywords, such as `_Static_assert`, `_Bool`, and `_Noreturn`, which do not have a C++ counterpart. | 
|  | These should be avoided in preference for macros that wrap them, such as `static_assert`, `bool`, and `noreturn`. | 
|  |  | 
|  | ### Preprocessor Macros | 
|  |  | 
|  | Macros are often necessary and reasonable coding practice C (as opposed to C++) projects. | 
|  | In contrast to the recommendation in the Google C++ style guide, exporting macros as part of the public API is allowed in C code. | 
|  | A typical use case is a header with register definitions. | 
|  |  | 
|  | ### Aggregate Initialization | 
|  |  | 
|  | C99 introduces designated initializers: when initializing a type of struct, array, or union type, it is possible to *designate* an initializer as being for a particular field or array index. | 
|  | For example: | 
|  | ```c | 
|  | my_struct_t s = { .my_field = 42 }; | 
|  | int arr[5] = { [3] = 0xff, [4] = 0x1b }; | 
|  | ``` | 
|  | With judicious use, designated initializers can make code more readable and robust; struct field reordering will not affect downstream users, and weak typing will not lead to surprising union initialization. | 
|  |  | 
|  | When initializing a struct or union, initializers within *must* be designated; array-style initialization (or mixing designated and undesignated initializers) is forbidden. | 
|  |  | 
|  | Furthermore, the nested forms of designated initialization are forbidden (e.g., `.x.y = foo` and `.x[0] = bar`), to discourage initialization of deeply nested structures with flat syntax. | 
|  | This may change if we find cases where this initialization improves readability. | 
|  |  | 
|  | When initializing an array, initializers *may* be designated when that makes the array more readable (e.g., lookup tables that are mostly zeroed). | 
|  | Mixing designated and undesignated initializers, or using nested initializers, is still forbidden. | 
|  |  | 
|  | ### Function Declarations | 
|  |  | 
|  | ***All function declarations in C must include a list of the function's parameters, with their types.*** | 
|  |  | 
|  | C functions declared as `return_t my_function()` are called "K&R declarations", and are type compatible with any list of arguments, with any types. | 
|  | Declarations of this type allow type confusion, especially if the function definition is not available. | 
|  |  | 
|  | The correct way to denote that a function takes no arguments is using the parameter type `void`. | 
|  | For example `return_t my_function(void)` is the correct way to declare that `my_function` takes no arguments. | 
|  |  | 
|  | The parameter names in every declaration should match the parameter names in the function definition. | 
|  |  | 
|  | ### Inline Functions | 
|  |  | 
|  | Functions that we strongly wish to be inlined, and which are part of a public interface, should be declared as an inline function. | 
|  | This annotation serves as an indication to the programmer that the function has a low calling overhead, despite being part of a public interface. | 
|  | Presence---or lack---of an `inline` annotation does not imply a function will---or will not---be inlined by the compiler. | 
|  |  | 
|  | [C11](#c-version) standardised inline functions, learning from the mistakes in C++ and various nonstandard extensions. | 
|  | This means there are many legacy ways to define an inline function in C. | 
|  | We have chosen to follow how C11 designed the `inline` keyword. | 
|  |  | 
|  | The function definition is written in a header file, with the keyword `inline`: | 
|  | ```c | 
|  | // in my_inline.h | 
|  | inline int my_inline_function(long param1) { | 
|  | // implementation | 
|  | } | 
|  | ``` | 
|  |  | 
|  | There should be exactly one compilation unit with a compatible `extern` declaration of the same function: | 
|  | ```c | 
|  | // in my_inline.c | 
|  | #include <my_inline.h> | 
|  | extern int my_inline_function(long param1); | 
|  | ``` | 
|  |  | 
|  | Any compilation unit that includes `my_inline.h` must be linked to the compilation unit with the extern declarations. | 
|  | This ensures that if the compiler chooses not to inline `my_inline_function`, there is a function definition that can be called. | 
|  | This also ensures that the function can be used via a function pointer. | 
|  |  | 
|  | ### Static Declarations | 
|  |  | 
|  | Declarations marked `static` must not appear in header files. | 
|  | Header files are declarations of public interfaces, and `static` definitions are copied, not shared, between compilation units. | 
|  |  | 
|  | This is especially important in the case of a polyglot header, since function-local static declarations have different, incompatible semantics in C and C++. | 
|  |  | 
|  | Functions marked `static` must not be marked `inline`. | 
|  | The compiler is capable of inlining static functions without the `inline` annotation. | 
|  |  | 
|  | ### Nonstandard Attributes | 
|  |  | 
|  | The following nonstandard attributes may be used: | 
|  | *   `section(<name>)` to put a definition into a given object section. | 
|  | *   `weak` to make a symbol definition have weak linkage. | 
|  | *   `interrupt` to ensure a function has the right prolog and epilog for interrupts (this involves saving and restoring more registers than normal). | 
|  | *   `packed` to ensure a struct contains no padding. | 
|  | *   `warn_unused_result`, to mark functions that return error values that should be checked. | 
|  |  | 
|  | It is recommended that other nonstandard attributes are not used, especially where C11 provides a standard means to accomplish the same thing. | 
|  |  | 
|  | All nonstandard attributes must be supported by both GCC and Clang. | 
|  |  | 
|  | Nonstandard attributes must be written before the declaration, like the following example, so they work with both declarations and definitions. | 
|  |  | 
|  | ```c | 
|  | __attribute__((section(".crt"))) void _crt(void); | 
|  | ``` | 
|  |  | 
|  | ### Nonstandard Compiler Builtins | 
|  |  | 
|  | In order to avoid a total reliance on one single compiler, any nonstandard compiler builtins (also known as intrinsics) should be used via a single canonical definition. | 
|  | This ensures changes to add compatibilty for other compilers are less invasive, as we already have a function to include a full implementation within. | 
|  |  | 
|  | All nonstandard builtins should be supported by both GCC and Clang. | 
|  | Compiler builtin usage is complex, and it is recommended that a compiler engineer reviews any code that adds new builtins. | 
|  |  | 
|  | In the following, `__builtin_foo` is the *builtin name* and `foo` is the corresponding *general name*. | 
|  |  | 
|  | ***The use of nonstandard compiler builtins must be hidden using a canonical, compatible definition.*** | 
|  |  | 
|  | There are two ways of providing this canonical definition, depending on what the builtin does. | 
|  |  | 
|  | For builtins that correspond to a C library function, the general name must be available to the linker, as the compiler may still insert a call to this function. | 
|  | Unfortunately, older versions of GCC do not support the `__has_builtin()` preprocessor function, so compiler detection of support for these builtins is next to impossible. | 
|  | In this case, a standards-compliant implementation of the general name must be provided, and the compilation unit should be compiled with `-fno-builtins`. | 
|  |  | 
|  | For builtins that correspond to low-level byte and integer manipulations, an [inline function](#inline-functions) should be provided with a general name, which contains a call to the builtin name itself, or an equivalent implementation. | 
|  | Only the general name may be called by users: for instance, `uint32_t __builtin_bswap32(uint32_t)` must not be called, instead users should use `inline uint32_t bswap32(uint32_t x)`. | 
|  | Where the general name is already taken by an incompatible host or device library symbol, the general name can be prefixed with the current C namespace prefix, for instance `inline uint32_t bitfield_bswap32(uint32_t x)` for a function in `bitfield.h`. | 
|  | Where the general name is a short acronym, the name may be expanded for clarity, for instance `__builtin_ffs` may have a canonical definition named `bitfield_find_first_set`. | 
|  | Where there are compatible typedefs that convey additional meaning (e.g. `uint32_t` vs `unsigned int`), these may be written instead of the official builtin types. | 
|  |  | 
|  | For builtins that cannot be used via a compatible function definition (e.g. if an argument is a type or identifier), there should be a single canonical preprocessor definition with the general name, which expands to the builtin. | 
|  |  | 
|  | ## Code Lint | 
|  |  | 
|  | The clang-format tool can check for adherence to this style guide. | 
|  | The repository contains a `.clang-format` file which configures clang-format according to the rules outlined in this style guide. | 
|  |  | 
|  | You can run clang-format on you changes by calling `git clang-format`. | 
|  |  | 
|  | ```sh | 
|  | cd $REPO_TOP | 
|  | # make changes to the code ... | 
|  | git add your_modified_file.c | 
|  | # format the staged changes | 
|  | git clang-format | 
|  | ``` | 
|  |  | 
|  | To reformat the whole tree the script `util/run-clang-format.sh` can be used. |