1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
<!-- SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com> -->
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
# 13. Tooling
The guide relies on tools for everything that can be checked mechanically. A project that adopts it turns them all on,
with warnings as errors, in CI and in the local build alike.
## 13.1 Compiler
The warning set below is given for Clang, and for `clang-cl` on Windows; `clang-tidy` and the thread-safety analysis
need Clang in any case. A project that also builds with GCC or MSVC enables their equivalent warnings, with warnings
as errors, in a CI job of its own.
### Flags
```text
-std=c++20
-fno-exceptions
-Wall -Wextra -Wpedantic -Werror
-Wshadow
-Wformat=2
-Wcast-align -Wcast-qual
-Wundef
-Wnull-dereference
-Wimplicit-fallthrough
-Wnon-virtual-dtor -Woverloaded-virtual
-Wextra-semi
-Wmissing-field-initializers
-Wdouble-promotion
-Wimplicit-int-conversion -Wimplicit-float-conversion
-Wdeprecated
-Wunreachable-code-aggressive
-Wvla
-Wthread-safety
-Wcomma
```
With `clang-cl`, each flag is passed as `/clang:<flag>`, and the language standard as `/std:c++20`.
These flags apply to first-party code only. Third-party code is compiled with its own options; its headers are included
as system headers (`-isystem`, or the build tool's equivalent), so their warnings do not fail the build.
### Optimized and debug builds
Debug builds keep assertions on and use `-O0` or `-Og`. Release builds use `-O2` or `-O3` with `NDEBUG`. CI builds both,
so that code that only compiles with assertions, or only without, is caught.
## 13.2 The clang-tidy profile
Copy this file to `.clang-tidy` at the root of the project and adjust the two path filters at the end. Every enabled
check is an error.
```yaml
---
Checks: >
-*,
clang-analyzer-*,
bugprone-*,
concurrency-*,
performance-*,
portability-*,
modernize-loop-convert,
modernize-make-unique,
modernize-redundant-void-arg,
modernize-type-traits,
modernize-use-equals-delete,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
misc-throw-by-value-catch-by-reference,
readability-duplicate-include,
readability-else-after-return,
readability-implicit-bool-conversion,
readability-inconsistent-declaration-parameter-name,
readability-make-member-function-const,
readability-misleading-indentation,
readability-redundant-access-specifiers,
readability-redundant-casting,
readability-redundant-control-flow,
readability-redundant-declaration,
readability-redundant-function-ptr-dereference,
readability-redundant-inline-specifier,
readability-redundant-smartptr-get,
readability-redundant-string-cstr,
readability-redundant-string-init,
readability-redundant-typename,
readability-simplify-boolean-expr,
readability-static-accessed-through-instance,
readability-uniqueptr-delete-release,
-bugprone-easily-swappable-parameters,
-bugprone-exception-escape,
-portability-avoid-pragma-once,
-modernize-use-auto,
-modernize-use-emplace,
-modernize-use-trailing-return-type,
-readability-braces-around-statements,
-readability-function-size,
-readability-magic-numbers,
-readability-qualified-auto,
-readability-redundant-member-init
WarningsAsErrors: '*'
HeaderFileExtensions:
- h
- hpp
ImplementationFileExtensions:
- c
- cpp
# First-party headers only; adjust to the project's source directories.
HeaderFilterRegex: '(^|.*/)(Source|Headers|Tests)/.*'
ExcludeHeaderFilterRegex: '(^|.*/)(build|third_party|external)/.*'
SystemHeaders: false
FormatStyle: file
CheckOptions:
readability-implicit-bool-conversion.AllowPointerConditions: false
readability-implicit-bool-conversion.AllowIntegerConditions: false
modernize-use-using.IgnoreExternC: true
modernize-use-using.IgnoreMacros: true
modernize-loop-convert.MinConfidence: reasonable
...
```
### Why some checks are off
| Check | Reason |
| --- | --- |
| `bugprone-easily-swappable-parameters` | flags most functions with two parameters of one type; [strong types](TYPES-AND-CLASSES.md#67-strong-types) address the real risk |
| `bugprone-exception-escape` | meaningless when exceptions are disabled |
| `portability-avoid-pragma-once` | the guide uses `#pragma once` on purpose |
| `modernize-use-auto` | the guide writes types that carry information ([Language](LANGUAGE.md#52-auto)) |
| `modernize-use-emplace` | `push_back` of a constructed value is clearer and equally fast after a move |
| `modernize-use-trailing-return-type` | the guide uses trailing return types, but not for `void` functions, which the check would rewrite |
| `readability-braces-around-statements` | braces are required by the guide; the check's fix-its fight `clang-format` |
| `readability-function-size`, `readability-magic-numbers` | judged in review; the fixed thresholds produce more noise than findings |
| `readability-qualified-auto` | conflicts with writing `auto` for pointers returned by APIs whose type is obvious |
| `readability-redundant-member-init` | aggregate members keep an explicit `{}` so aggregate initialization that omits trailing fields stays clean under `-Wmissing-field-initializers` |
### Naming
Naming is checked in review, not by `readability-identifier-naming`. The check can enforce casing, but it cannot tell
a constant that deserves `kPascalCase` from an immutable local, and its exceptions for third-party callbacks grow into a
second configuration. A project may enable it once its code is consistent.
## 13.3 Other checks
| Tool | Checks |
| --- | --- |
| `clang-format --dry-run --Werror` | every file is formatted by the profile |
| Doxygen, warnings as errors | every public declaration is documented |
| A header self-containment build | every public header compiles on its own |
| The C interface test | each C header compiles as C11 and is called from C |
| Sanitizer and fuzzer jobs | see [Testing](TESTING.md) |
| The Clang Static Analyzer | the `clang-analyzer-*` checks over every translation unit |
## 13.4 Versions
Pin the exact versions of Clang, `clang-format` and `clang-tidy` that CI uses, and use the same versions locally. A
different version can format a file differently or report a check the CI version does not have. A version upgrade is
its own change: it updates the pin, reformats or fixes what the new version reports, and nothing else.
|