Skip to contentSkip to conversation

clang-format: add configuration file

PATCH Superseded Miguel Ojeda 3 participants 7 messages Mar 12, 2018 – Mar 14, 2018

Subsystems (3)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 clang-format: add configuration file

clang-format is a tool to format C/C++/... code according to a set of rules and heuristics. Like all tools, it is not perfect nor covers every single case, but it is good enough to be helpful.

In particular, it is useful for quickly re-formatting blocks of code, spotting coding style mistakes, sorting #includes, aligning variables/ comments/macro endings, reflowing text, etc. It also serves as a teaching tool/guide for newcomers.

The tool itself has been already included in the repositories of popular Linux distributions for a long time. The rules in this file are intended for clang-format >= 4, which is easily available in most distributions.

This commit adds the configuration file that contains the rules that the tool uses to know how to format the code according to the kernel coding style. This gives us two advantages:

* clang-format works out of the box with reasonable defaults; avoiding that everyone has to re-do the configuration.

* Everyone agrees (eventually) on what is the most useful default configuration for most of the kernel.

Some of clang-format's features relevant for the kernel are:

* Uses clang's tooling support behind the scenes to parse and rewrite the code. It is not based on ad-hoc regexps.

* Supports reasonably well the Linux kernel coding style.

* Fast enough to be used at the press of a key.

* There are already integrations (either built-in or third-party) for many common editors used by kernel developers (e.g. vim, emacs, Sublime, Atom...) that allow you to format an entire file or, more usefully, just your selection.

* Able to parse unified diffs -- you can, for instance, reformat only the lines changed by a git commit.

* Able to reflow text comments as well.

* Widely supported and used by hundreds of developers in highly complex projects and organizations (e.g. the LLVM project itself, Chromium, WebKit, Google, Mozilla...). Therefore, it should be supported for a long time.

See more information about the tool at:

https://clang.llvm.org/docs/ClangFormat.html
https://clang.llvm.org/docs/ClangFormatStyleOptions.html

Cc Randy Dunlap <[email protected]>
Cc Andy Whitcroft <[email protected]>
Cc Joe Perches <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Andrew Morton <[email protected]>
---
 .clang-format                          | 107 +++++++++++++++++++++++++++++++++
 .gitignore                             |   1 +
 Documentation/process/4.Coding.rst     |   6 ++
 Documentation/process/coding-style.rst |   6 ++
 4 files changed, 120 insertions(+)
 create mode 100644 .clang-format
.clang-format new file +107 -0
new file mode 100644
index 000000000000..de2e083be674
@@ -0,0 +1,107 @@
+# Intended for clang-format >= 4
+---
+AccessModifierOffset: -4
+AlignAfterOpenBracket: DontAlign
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
+AlignOperands: false
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+  AfterClass: false
+  AfterControlStatement: false
+  AfterEnum: true
+  AfterFunction: true
+  AfterNamespace: true
+  AfterObjCDeclaration: false
+  AfterStruct: true
+  AfterUnion: true
+  #AfterExternBlock: true # Unknown to clang-format-5.0
+  BeforeCatch: false
+  BeforeElse: false
+  IndentBraces: false
+  #SplitEmptyFunction: true # Unknown to clang-format-4.0
+  #SplitEmptyRecord: true # Unknown to clang-format-4.0
+  #SplitEmptyNamespace: true # Unknown to clang-format-4.0
+BreakBeforeBinaryOperators: All
+BreakBeforeBraces: Custom
+#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+#CompactNamespaces: false # Unknown to clang-format-4.0
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 8
+ContinuationIndentWidth: 8
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+#FixNamespaceComments: false # Unknown to clang-format-4.0
+ForEachMacros:
+#IncludeBlocks: Preserve # Unknown to clang-format-5.0
+IncludeCategories:
+  - Regex: '.*'
+    Priority: 1
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+#IndentPPDirectives: None # Unknown to clang-format-5.0
+IndentWidth: 8
+IndentWrappedFunctionNames: true
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: Inner
+#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
+ObjCBlockIndentWidth: 8
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: true
+#PenaltyBreakAssignment: 2 # Unknown to clang-format-4.0
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+ReflowComments: false
+SortIncludes: true
+#SortUsingDeclarations: true # Unknown to clang-format-4.0
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
+#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
+SpaceBeforeParens: ControlStatements
+#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp03
+TabWidth: 8
+UseTab: Always
+...
+
.gitignore +1 -0
index 1be78fd8163b..ab5cbc1e85f6 100644
@@ -81,6 +81,7 @@ modules.builtin
 !.gitignore
 !.mailmap
 !.cocciconfig
+!.clang-format
 
 #
 # Generated include files
Documentation/process/4.Coding.rst +6 -0
index 26b106071364..d4bdbb17f2f5 100644
@@ -58,6 +58,12 @@ can never be transgressed.  If there is a good reason to go against the
 style (a line which becomes far less readable if split to fit within the
 80-column limit, for example), just do it.
 
+Note that you can use the clang-format tool to help you with these rules
+and to quickly re-format parts of your code automatically. It is specially
+useful for new files/code and to spot coding style mistakes. It is also
+useful to sort #includes, to align variables or comments, to reflow text
+and other similar tasks.
+
 
 Abstraction layers
 ******************
Documentation/process/coding-style.rst +6 -0
index a20b44a40ec4..ceac420cd9ec 100644
@@ -622,6 +622,12 @@ options ``-kr -i8`` (stands for ``K&R, 8 character indents``), or use
 re-formatting you may want to take a look at the man page.  But
 remember: ``indent`` is not a fix for bad programming.
 
+Note that you can also use the clang-format tool to help you with these rules
+and to quickly re-format parts of your code automatically. It is specially
+useful for new files/code and to spot coding style mistakes. It is also
+useful to sort #includes, to align variables or comments, to reflow text
+and other similar tasks.
+
 
 10) Kconfig configuration files
 -------------------------------
Signature · 1 line
2.14.1
#1 lore raw
Quoted 3 lines · Miguel Ojeda

clang-format is a tool to format C/C++/... code according to a set of rules and heuristics. Like all tools, it is not perfect nor covers every single case, but it is good enough to be helpful.

Yes, thanks.

It'd also be nice to remove Lindent as clang-format is a much better tool today and indent is unmaintained for about a decade.

#2 lore raw
In reply to Miguel Ojeda

Documentation/process/4.Coding.rst can never be transgressed. If there is a good reason to go against the · line 65

Quoted 11 lines · On Tue, 13 Mar 2018 00:39:52 +0100 Miguel Ojeda…
Documentation/process/4.Coding.rst +5 -0
@@ -58,6 +58,12 @@ can never be transgressed.  If there is a good reason to go against the
 style (a line which becomes far less readable if split to fit within the
 80-column limit, for example), just do it.
 
+Note that you can use the clang-format tool to help you with these rules
+and to quickly re-format parts of your code automatically. It is specially
+useful for new files/code and to spot coding style mistakes. It is also
+useful to sort #includes, to align variables or comments, to reflow text
+and other similar tasks.

It would be rather helpful to tell people how to invoke clang-format. Is it just "clang-format foo.c" or what?

#3 lore raw
Quoted 8 lines · Andrew Morton
Quoted 6 lines · On Tue, 13 Mar 2018 00:39:52 +0100 Miguel Ojeda…
Documentation/process/4.Coding.rst +0 -0
@@ -58,6 +58,12 @@ can never be transgressed.  If there is a good reason to go against the
 style (a line which becomes far less readable if split to fit within the
 80-column limit, for example), just do it.
 
Quoted 9 lines

Documentation/process/4.Coding.rst can never be transgressed. If there is a good reason to go against the · line 65

Quoted 5 lines
Documentation/process/4.Coding.rst +5 -0
+Note that you can use the clang-format tool to help you with these rules
+and to quickly re-format parts of your code automatically. It is specially
+useful for new files/code and to spot coding style mistakes. It is also
+useful to sort #includes, to align variables or comments, to reflow text
+and other similar tasks.

It would be rather helpful to tell people how to invoke clang-format. Is it just "clang-format foo.c" or what?

Indeed! I will add more information. Here is some more we can put (I will properly rewrite it, but you can see it as a draft and as the answer to your question! :-)

You can call "clang-format foo.c" and it will output to the standard output the formatted file (using the configuration file automatically if it is any of the parents, a la git). The -i does the replacements inline. However, for the kernel, it is best to use it with one of the editor integrations: the issue is that clang-format does not format everything perfectly as we want for the kernel [*], so it is best used to either 1) format portions of files or 2) check patches.

- For formatting portions of files, you just select inside your text
editor something and press your favorite key binding to re-format it (clang-format has some parameters that the editor passes when invoking it). Since it is very fast, it works very well. Integrations with vim and emacs come with the tool; for most other popular editors, you can usually find a plugin or similar in the manager of such editor.

- For checking patches, since it comes with support to read unified
diffs, it is very easy to use it for patches and for commits. What you will see is both things that could be improved because there was a typo/mistake by the patch author, and things that you should ignore because clang-format does not format those cases -- it is very easy to know which are which if you use the tool a few times, specially if you are looking at the difference with git diff.

When I was testing clang-format to come with the configuration, I was running the tool against full files, and while there were many cases that have to be ignored, like [*], it is also very easy to see some mistakes in the code. If it gets popular, I am sure people will come up with ready-to-be-used scripts/hooks and things like that, but for the moment I thought the best was to at least have the basic configuration in and iterate from there. At least there is *one* person (what an audience! :-) using it currently, since if you grep for "clang-format" you will see one staging driver with one comment in the code to turn off the formatting in a block. I also thought that the sooner we define how we will use it (e.g. whether we allow those "don't-format-this" marks, the name for those marks -- it is configurable, etc.), the best.

[*] For instance, it does not support alignment of one-line #defines -- but it aligns multiline #defines quite well, though. So you won't run it for full files typically, but for groups of things. Another simple case where it is best for selections and not for full files (at least existing files) is the sorting of #includes i.e. It is great if you use it when selecting a bunch of them that you know will look better if sorted, but probably you don't want to sort ALL of them (even if it respects the grouping, which it does); expect if you are writing a new file.

Cheers,
Miguel

#4 lore raw
Quoted 8 lines · Miguel Ojeda
Quoted 7 lines · Andrew Morton
Quoted 6 lines · On Tue, 13 Mar 2018 00:39:52 +0100 Miguel Ojeda…
Documentation/process/4.Coding.rst +0 -0
@@ -58,6 +58,12 @@ can never be transgressed.  If there is a good reason to go against the
 style (a line which becomes far less readable if split to fit within the
 80-column limit, for example), just do it.
 
Quoted 7 lines
Quoted 7 lines

Documentation/process/4.Coding.rst can never be transgressed. If there is a good reason to go against the · line 65

Quoted 5 lines
Documentation/process/4.Coding.rst +5 -0
+Note that you can use the clang-format tool to help you with these rules
+and to quickly re-format parts of your code automatically. It is specially
+useful for new files/code and to spot coding style mistakes. It is also
+useful to sort #includes, to align variables or comments, to reflow text
+and other similar tasks.

It would be rather helpful to tell people how to invoke clang-format.

clang-format has its drawbacks but at least it is
likely to be improved more in the future.

That is a lot better than Lindent/indent.

Some not kernel-style compliant oddities:

o placements of braces for definitions is like:
static const struct pci_device_id e100_id_table[]

       = { INTEL_8255X_ETHERNET_DEVICE(0x1029, 0),

o alignment of block #defines
o alignment of function arguments
o logical tests continuations moved to BOL not EOL
o misalignment of per-line comments
o location of struct/union/enum braces

etc...

After applying Miguel's patch, try it with something like:

$ git ls-files -- "drivers/net/ethernet/intel/*.[ch]" | \
  while read file ; do clang-format -i $file ; done

and look at the diff (I used clang-format-5.0.0-3)

#5 lore raw
Quoted 20 lines · Joe Perches
Quoted 8 lines · Miguel Ojeda
Quoted 7 lines · Andrew Morton
Quoted 6 lines · On Tue, 13 Mar 2018 00:39:52 +0100 Miguel Ojeda…
Documentation/process/4.Coding.rst +0 -0
@@ -58,6 +58,12 @@ can never be transgressed.  If there is a good reason to go against the
 style (a line which becomes far less readable if split to fit within the
 80-column limit, for example), just do it.
 
Quoted 7 lines
Quoted 7 lines

Documentation/process/4.Coding.rst can never be transgressed. If there is a good reason to go against the · line 65

Quoted 5 lines
Documentation/process/4.Coding.rst +5 -0
+Note that you can use the clang-format tool to help you with these rules
+and to quickly re-format parts of your code automatically. It is specially
+useful for new files/code and to spot coding style mistakes. It is also
+useful to sort #includes, to align variables or comments, to reflow text
+and other similar tasks.

It would be rather helpful to tell people how to invoke clang-format.

clang-format has its drawbacks but at least it is
likely to be improved more in the future.

Quoted 8 lines

That is a lot better than Lindent/indent.

Some not kernel-style compliant oddities:

o placements of braces for definitions is like:
static const struct pci_device_id e100_id_table[]

       = { INTEL_8255X_ETHERNET_DEVICE(0x1029, 0),

o alignment of block #defines

You mean a series of one-line #defines (i.e. the body) or a multiline #define (i.e. the backspaces)? For the former, indeed, it is what I saw. It seems that clang-format treats it one by one, and it honors the column width limitation (so if it does not fit in one line, it will move it to the next). However, if it fits, it will leave it in the same line without aligning the bodies of the other #defines.

Quoted 1 line

o alignment of function arguments

For function signatures in general, I am unsure what options to apply... I have seen in many places the "indent until the ( in the previous line", then again, I have seen the "1 tab indentation" style as well. I have also seen the GNU style (I mean leaving the return type and other specifiers in the previous line) is also present when it does not fit in one line. The coding style guide says:

"Statements longer than 80 columns will be broken into sensible chunks, unless exceeding 80 columns significantly increases readability and does not hide information. Descendants are always substantially shorter than the parent and are placed substantially to the right. The same applies to function headers with a long argument list. However, never break user-visible strings such as printk messages, because that breaks the ability to grep for them. "

Quoted 1 line

o logical tests continuations moved to BOL not EOL

Changed for v2. It does not seem to say anything in the coding style guide, but you are completely right, it is the prevalent style.

Quoted 2 lines

o misalignment of per-line comments
o location of struct/union/enum braces

Oops -- fixed.

Quoted 9 lines

etc...

After applying Miguel's patch, try it with something like:

$ git ls-files -- "drivers/net/ethernet/intel/*.[ch]" | \
  while read file ; do clang-format -i $file ; done

and look at the diff (I used clang-format-5.0.0-3)

Thanks a lot for the list/review! It was very useful.

Since we seem to agree on having this, I will send a v2 after I try a few experiments to try to reduce more the produced diffs, explain things better in Documentation/, add more comments in the config file and send a v2.

Cheers,
Miguel

#6 lore raw
Quoted 5 lines · Miguel Ojeda

Since we seem to agree on having this, I will send a v2 after I try a few experiments to try to reduce more the produced diffs, explain things better in Documentation/, add more comments in the config file and send a v2.

Alright, time for a fun fact: roughly 11 hours after I sent the first message, Microsoft announces they are going to support clang-format in Visual Studio 15.7:

https://blogs.msdn.microsoft.com/vcblog/2018/03/13/clangformat-support-in-visual-studio-2017-15-7-preview-1/

Talk about coincidences... :-)

On related news, Google also announced that they are compiling Chrome with clang on Windows a week or so ago...

Cheers,
Miguel

[*] Their timestamp: <time class="entry-date published" datetime="2018-03-13T11:13:51+00:00">March 13, 2018</time>