. . . I am now free to return to banging my fucking head against the wall trying to make clang-format (as packaged in VS 2019) actually do what I want it to do. Because, you know, that’s something easy to accomplish.
My head still has bruises from my fights with clang-format. I can’t say I’m 100% happy with the current cease-fire, but I have been able to coax clang into doing something … passable … with NDIS code.
The hard part was SAL annotations. I eventually solved that using a feature that was just introduced in the very recent clang 9.0 release: StatementMacros
. This 9.0 release isn’t currently bundled with Visual Studio, so you have to download it separately and configure VS to use your custom clang-format.exe. Tools > Options > Text Editor > C/C++ > Formatting > General > Use custom clang-format.exe file.
Then in your .clang-format, put something like this:
StatementMacros: [
'EXTERN_C',
'_At_',
'_When_',
'_Success_',
'_Check_return_',
'_Must_inspect_result_',
'_IRQL_requires_',
'_IRQL_requires_max_',
'_IRQL_requires_min_',
'_IRQL_saves_',
'_IRQL_restores_',
'_IRQL_saves_global_',
'_IRQL_restores_global_',
'_IRQL_raises_',
'_IRQL_lowers_',
'_Acquires_lock_',
'_Releases_lock_',
'_Acquires_exclusive_lock_',
'_Releases_exclusive_lock_',
'_Acquires_shared_lock_',
'_Releases_shared_lock_',
'_Requires_lock_held_',
'_Use_decl_annotations_',
'_Guarded_by_',
]
That’ll ensure that each function-level annotation winds up on its own line, like this:
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS Foo()
{
return STATUS_NOT_IMPLEMENTED;
}
Another tip for drivers. If you use WPP tracing, you’ll probably want this .clang-format directive:
CommentPragmas: '^begin_wpp|^end_wpp'
Otherwise, clang-format will permit itself to mangle the special //begin_wpp
comment blocks.
That all being said, there’s still brokenness here. For example, clang-format recognizes __declspec
as a built-in token, so it won’t let you hack it using StatementMacros
. So NDIS code currently has this unfortunate spot of indentation:
__declspec(noinline)
VOID ndisNblTrackerDebugBreak(. . . something . . .)
{
. . .;
}
I also have some issues with clang-format’s “binpacking” of arguments, but that’s a general style issue and not specific to drivers, so I’ll not discuss it here.