Open phillipjohnston opened 7 years ago
Clang 5 was released last week.
It's a good opportunity to talk about a not-enough-known tool: Clang-format.
Clang-format is part of the Clang project but can be used without the Clang compiler. It's an independent executable.
Clang-format is a code linter for C++. It takes a non-formatted code as input and produces a well-formatted code as output. The result is instantaneous.
Clang-format comes with predefined settings form well-known coding styles, like Google, LLVM and Mozilla. But you can also define your own style by writing a .clang-format file.
The .clang-format file describes the coding style to be used. It supports tens of settings and we'll see in this article what new settings have been added.
Don't miss the conclusion were I share four pro-tips to integrate Clang-format in your workflow.
New options
AlignEscapedNewlines
This option affects the position of the backslashes in a macro definition.
AlignEscapedNewlines has three possible values: DontAlign, Left and Right.
If set to DontAlign, backslashes are not aligned:
#define A \
int aaaa; \
int b; \
int dddddddddd;
If set to Left, backslashes are aligned and pushed to the left:
#define A \
int aaaa; \
int b; \
int dddddddddd;
If set to Right, backslashes are aligned and pushed to the right:
#define A \
int aaaa; \
int b; \
int dddddddddd;
In this case the position depends on the number of columns configured in ColumnLimit.
AlignEscapedNewlines replaces the boolean AlignEscapedNewlinesLeft which produced the same result as the new Left value.
BreakBeforeInheritanceComma
This option specifies the way inheritances are written. It's only use when there is multiple inheritance.
BreakBeforeInheritanceComma can be set to either true or false.
If set to true, it puts each inheritance on a new line:
class MyClass
: public X
, public Y {
};
If set to false, it puts everything on a single line:
class MyClass : public X, public Y {
};
BreakConstructorInitializers
This option specifies the way initializers are written in a constructor.
BreakConstructorInitializers has three possible values: BeforeColon, BeforeComma and AfterColon.
If set to BeforeColon, the colon is on the left and all commas are on the right:
Constructor()
: initializer1(),
initializer2()
If set to BeforeComma, the colon and all commas are on the left:
Constructor()
: initializer1()
, initializer2()
If set to AfterColon, the colon and all commas are on the right:
Constructor() :
initializer1(),
initializer2()
BreakConstructorInitializers replaces the boolean BreakConstructorInitializersBeforeComma which produced the same result as BeforeComma.
CompactNamespaces
This setting changes the way consecutive namespace declaration are written.
CompactNamespaces can be set to either true or false.
If set to true, consecutive namespaces are written on the same line:
namespace Foo { namespace Bar {
}}
If set to false, consecutive namespaces are written on different lines:
namespace Foo {
namespace Bar {
}
}
FixNamespaceComments
When enabled, this adds a comment at the end of each namespace.
FixNamespaceComments can be set to either true or false.
If set to true, Clang-format adds a comment with the name of the namespace.
namespace a {
foo();
} // namespace a
This is very useful as a namespace rarely fits in a single screen.
If you rename the namespace, the Clang-format will adjust the comment accordingly; the two will always be in-sync.
You can combine this option with the previous one and get the following result:
namespace Foo { namespace Bar {
}} // namespace Foo::Bar
ShortFunctionStyle: InlineOnly
This is a new value for an existing option. It adds finer control on which short functions are allowed to be on a single line.
If ShortFunctionStyle is set to InlineOnly, only short functions that are defined inside a class are written on a single line:
class Foo {
void f() { foo(); }
};
void f() {
foo();
}
void f() {
}
This is a complement to the Inline value which also put empty top-level functions in a single line:
class Foo {
void f() { foo(); }
};
void f() {
foo();
}
void f() {}
SplitEmptyFunction
This setting affects the way empty function are written.
It's only used when the opening brace is on a new line, i.e. only when BraceWrapping/AfterFunction is true.
SplitEmptyFunction can be set to either true or false.
If set to true, an empty function will take three lines:
int f()
{
}
If set to false, an empty function will only take two lines:
int f()
{}
SplitEmptyRecord
This setting is similar to the previous one excepts that it affects struct, class and union.
If set to true, an empty class will take three lines:
class Foo
{
}
If set to false, an empty class will only take two lines:
class Foo
{}
SplitEmptyNamespace
This setting is similar to the previous one excepts that it affects namespaces.
If set to true, an empty namespace will take three lines:
namespace Foo
{
}
If set to false, an empty namespace will only take two lines:
namespace Foo
{}
SortUsingDeclaration
When enabled, this option sort using declaration in alphabetical order. Clang-format 4 was already able to sort #include, now it can do the same with using declarations.
SortUsingDeclaration can be either true or false.
If set to true, using declarations will be written in alphabetical order:
using std::cin;
using std::cout;
If set to false, they are left as is:
using std::cout;
using std::cin;
It's possible to add priority to certain #include directives using the option IncludeCategories, but there is no such feature for using declarations.
IndentPPDirectives (v6 only)
This setting is not available in Clang-format 5, but will be in version 6 and is already available in the trunk.
It enables indentation of preprocessor directives.
IndentPPDirectives can be set to either None or AfterHash.
If set to None, the preprocessor directives are not indented:
#if FOO
#if BAR
#include <foo>
#endif
#endif
If set to AfterHash, they are indented with spaces placed after the hash sign:
#if FOO
# if BAR
# include <foo>
# endif
#endif
It's not yet possible to have the spaces before the hash, but one can assume that a BeforeHash will be added in a very near future.
Clang-format is clever enough to detect include-guards. If you have a header surrounded by a #ifndef/#define/#endif, this will be detected as an include-guard and will not be indented.
Clang recently updated, and new formatting rules are available. I should migrate to clang-5.