blob: 73902a557bf9dc12c48e3c39e917763d3401c233 [file] [log] [blame] [view]
{{% lowrisc-doc-hdr 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
{{% toc 3 }}
### 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++.***
***Variables mentioned in comments should be delimited with pipe (`|`) characters.***
Example:
```c
// |ptr| can never be NULL for reasons.
```
### 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.
Example:
```c
// TODO: This algorithm should be rewritten to be more efficient.
// (Bug lowrisc/reponame#27)
```
### 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.
Example:
```c
/**
* Do something amazing
*
* Create a rainbow and place a unicorn at the bottom of it. @p arg1 pots of
* gold will be positioned on the east end of the 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);
```
## 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.
### 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.
### 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.
## 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.