ClangFormat实践

clang-format的使用

使用预定义的编码风格

1
2
clang-format -i hello.c                     # 若当前目录下存在.clang-format文件时,使用.clang-format定义的编码风格格式化hello.c,否则使用预定义的LLVM编码风格格式化hello.c
clang-format -i --style=Google hello.c # 使用预定义的Google编码风格格式化hello.c

使用文件中定义的编码风格

1
2
clang-format -i --style=file hello.c            # 使用当前或父目录中的.clang-format文件中定义的编码风格格式化hello.c
clang-format -i --style=file:stylePath hello.c # 使用stylePath文件中定义的编码风格格式化hello.c,stylePath可以是绝对或相对路径

生成和自定义配置

使用–dump-config选项,可以生成所使用的clang-format版本支持的所有配置项,然后可以参考Clang-Format Style Options定制自己想要的,如下命令生成Google编码风格的配置:

1
clang-format --style=google --dump-config > .clang-format

实例:自定义Linux Kernel的格式化配置文件

自2018年4月起,Linux Kernel的源代码里已经增加了一个.clang-format文件,按照Linux kernel coding style来定制了clang-format的格式化选项。但这仍存在几个问题:

  • 没有指定确定的clang-format版本,仅说明在4.0版本以上,然而,更高版本的clang-format可能会不再支持某些配置项(这问题可以通过指定–Wno-error=unknown来解决),更糟糕的是某些配置项的类型改变了,例如:原来的配置项是布尔型的,支持的是true或false,在新的版本里,可能变成了枚举类型以支持多样性,此时,配置文件必须修改才能使用。从内核自带的.clang-format文件中,存在多个配置项被注释掉也能看得出来
  • 内核自带的.clang-format并没有利用上新版本的clang-format的更多特性,这些新特性可能使得格式化操作更贴合内核编码风格的需求

为此,我们可以分几步对此进行改进:
1.首先选定所使用的clang-format版本,截止此时的稳定发行版为clang-format 14.0
2.复制内核原有的.clang-format为.clang-format-14
3.使用clang-format --style=Google --dump-config > .clang-format-google生成一个预定义的配置文件
4.比较.clang-format-14和.clang-format-google可以看到有很多配置不同,但我们仅关注类型改变了的,及.clang-format-14缺少了的配置项,例如AlignConsecutiveAssignments在.clang-format-14中是boolean型的false,在.clang-format-google却是None,这种属于类型改变。而AlignConsecutiveMacros则是.clang-format-14中缺少的配置项。根据文件比较出来的不同,及Clang-Format Style Options的描述,在不改变.clang-format-14原有配置项的含义和内核编码风格的前提下,按需把配置项的值转换为新类型的,并加上缺少的部分,就形成了一个完整的适配于clang-format 14.0的版本
5.之后可以用clang-format -i --style=file:<path-to-.clang-format-14> file.c命令来格式化内核代码

以下是本人的配置范例:

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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
# 用于Linux Kernel的clang-format配置文件,验证的clang-format版本为14.0
#
# Copyright (C) 2022-2022 Oak Chen <oak@sfysoft.com>
#
# 本配置文件基于Linux Kernel v5.16-rc5-90-gef8dd01538ea自带的.clang-format,
# 再使用clang-format 14.0版本,以--dump-config --style=Google
# 生成配置,整合缺少的配置,适配为clang-format 14版本,并增加注释而成
#
# 更多的信息可以参考
# Documentation/process/clang-format.rst
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
# BasedOnStyle: InheritParentConfig
AccessModifierOffset: -4 # 访问修饰符(如public)的缩进或凸出
AlignAfterOpenBracket: Align # 在开括号处对齐参数
AlignArrayOfStructures: None # 初始化结构体里面的数组时,对齐表达式的值,clang-format 13
AlignConsecutiveAssignments: None # 对齐连续赋值时的赋值符
AlignConsecutiveBitFields: None # 对齐连续的位域分隔符(即:),clang-format 11
AlignConsecutiveDeclarations: None # 对齐连续定义的变量名
AlignConsecutiveMacros: None # 对齐连续宏定义时的值,clang-format 9
AlignEscapedNewlines: Left # 对齐\续行时的\,clang-format 5
AlignOperands: Align # 对齐分成多行的表达式的操作数
AlignTrailingComments: false # 对齐行尾的注释
AllowAllArgumentsOnNextLine: false # 允许所有实参在下一行,clang-format 9
AllowAllParametersOfDeclarationOnNextLine: false # 允许定义时的所有参数在下一行
AllowShortBlocksOnASingleLine: Never # 允许短代码块写在一行
AllowShortCaseLabelsOnASingleLine: false # 允许短的case标签写在一行
AllowShortEnumsOnASingleLine: false # 允许短的枚举值在同一行
AllowShortFunctionsOnASingleLine: None # 允许短函数写在一行
AllowShortIfStatementsOnASingleLine: Never # 允许短的if语句写在一行
AllowShortLambdasOnASingleLine: All # 允许短的lambda表达式写在一行,clang-format 9
AllowShortLoopsOnASingleLine: false # 允许短循环写在一行
AlwaysBreakAfterDefinitionReturnType: None # 函数定义处的返回类型后是否换行
AlwaysBreakAfterReturnType: None # 函数声明处的返回类型后是否换行
AlwaysBreakBeforeMultilineStrings: false # 多行拼接的字符串前是否换行,即字符串的起始行是否另起一行
AlwaysBreakTemplateDeclarations: Yes # 模板定义时,是否在定义前换行,clang-format 7
AttributeMacros: # 可视为属性或限定符的宏,常用于编译器扩展,clang-format 12
- __capability
BinPackArguments: true # 函数调用时,参数尽可能在同一行,false为每行一个参数
BinPackParameters: true # 函数定义时,参数尽可能在同一行,false为每行一个参数
BitFieldColonSpacing: Both # 位域:前后加空格,clang-format 12
BraceWrapping: # 自定义的{换行规则
AfterCaseLabel: false # 在case标签后换行
AfterClass: false # 在class后换行
AfterControlStatement: Never # 在控制语句后换行
AfterEnum: false # 在枚举定义后换行
AfterFunction: true # 在函数定义后换行
AfterNamespace: true # 在命名空间定义后换行
AfterObjCDeclaration: false # 在Objective C定义(接口、实现等)后换行
AfterStruct: false # 在结构体定义后换行
AfterUnion: false # 在联合体定义后换行
AfterExternBlock: false # 在extern "C"这种声明后换行,clang-format 11
BeforeCatch: false # 在catch语句前换行
BeforeElse: false # 在else语句前换行
BeforeLambdaBody: false # 在lambda定义体前换行
BeforeWhile: false # 在do while的while前换行
IndentBraces: false # 缩进{
SplitEmptyFunction: true # 拆分空的函数体
SplitEmptyRecord: true # 拆分空的class、struct、union等定义
SplitEmptyNamespace: true # 拆分空的namespace定义
BreakAfterJavaFieldAnnotations: false # 在Java的注解器后换行
BreakBeforeBinaryOperators: None # 在二元操作符前换行
BreakBeforeBraces: Custom # 自定义{前的换行,规则由BraceWrapping指定
BreakBeforeConceptDeclarations: true # 在concept前换行,clang-format 12
BreakBeforeInheritanceComma: false # 继承时,在,前换行,clang-format 15不支持
BreakBeforeTernaryOperators: false # 在三行表达式的操作符前换行
BreakConstructorInitializersBeforeComma: false # 在构造器的初始化列表前的:前换行,已被BreakConstructorInitializers取代
BreakConstructorInitializers: BeforeComma # 在构造器的初始化列表中,在:和,前换行,并对齐:和,,clang-format 5
BreakInheritanceList: BeforeColon # 使用继承列表时,在:前换行,clang-format 7
BreakStringLiterals: false # 字符串字面值折成多行
ColumnLimit: 80 # 以单字节字符为单位的列宽度限制
CommentPragmas: '^ IWYU pragma:' # 注释里面的特别含义指示行,这里面包含的行不会被拆分
CompactNamespaces: false # 合并连续的命名空间定义到一行,clang-format 5
ConstructorInitializerAllOnOneLineOrOnePerLine: false # 构造器的初始化列表写在一行还是每个初始值一行
ConstructorInitializerIndentWidth: 8 # 构造器初始化列表缩进宽度
ContinuationIndentWidth: 8 # 连续缩进宽度
Cpp11BracedListStyle: false # 使用C++11的大括号里面的值列表风格,主要是第一个值前面和最后一个值后不加空格
DeriveLineEnding: false # 分析待格式化的文件以发现最常用的行结尾符,若不确定,则使用“\r\n”,clang-format 10
DerivePointerAlignment: false # 分析待格式化的文件以发现最常用的指针对齐风格,若不确定,则使用PointerAlignment的定义
DisableFormat: false # 完全禁止格式化
EmptyLineAfterAccessModifier: Never # 访问修饰符(public等)后添加空行,clang-format 13
EmptyLineBeforeAccessModifier: LogicalBlock # 访问修饰符(public等)前添加空行,clang-format 12
ExperimentalAutoDetectBinPacking: false # 检测函数定义和调用时,是否一个参数占用一行
FixNamespaceComments: false # 为较短的namespace添加缺失的结束注释(// namespace X),怎样的视为“短”由ShortNamespaceLines控制,clang-format 5

# Taken from:
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
# | sort | uniq
ForEachMacros: # 视为foreach循环而非函数调用的宏
- 'apei_estatus_for_each_section'
- 'ata_for_each_dev'
- 'ata_for_each_link'
- '__ata_qc_for_each'
- 'ata_qc_for_each'
- 'ata_qc_for_each_raw'
- 'ata_qc_for_each_with_internal'
- 'ax25_for_each'
- 'ax25_uid_for_each'
- '__bio_for_each_bvec'
- 'bio_for_each_bvec'
- 'bio_for_each_bvec_all'
- 'bio_for_each_integrity_vec'
- '__bio_for_each_segment'
- 'bio_for_each_segment'
- 'bio_for_each_segment_all'
- 'bio_list_for_each'
- 'bip_for_each_vec'
- 'bitmap_for_each_clear_region'
- 'bitmap_for_each_set_region'
- 'blkg_for_each_descendant_post'
- 'blkg_for_each_descendant_pre'
- 'blk_queue_for_each_rl'
- 'bond_for_each_slave'
- 'bond_for_each_slave_rcu'
- 'bpf_for_each_spilled_reg'
- 'btree_for_each_safe128'
- 'btree_for_each_safe32'
- 'btree_for_each_safe64'
- 'btree_for_each_safel'
- 'card_for_each_dev'
- 'cgroup_taskset_for_each'
- 'cgroup_taskset_for_each_leader'
- 'cpufreq_for_each_entry'
- 'cpufreq_for_each_entry_idx'
- 'cpufreq_for_each_valid_entry'
- 'cpufreq_for_each_valid_entry_idx'
- 'css_for_each_child'
- 'css_for_each_descendant_post'
- 'css_for_each_descendant_pre'
- 'device_for_each_child_node'
- 'displayid_iter_for_each'
- 'dma_fence_chain_for_each'
- 'do_for_each_ftrace_op'
- 'drm_atomic_crtc_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane_state'
- 'drm_atomic_for_each_plane_damage'
- 'drm_client_for_each_connector_iter'
- 'drm_client_for_each_modeset'
- 'drm_connector_for_each_possible_encoder'
- 'drm_for_each_bridge_in_chain'
- 'drm_for_each_connector_iter'
- 'drm_for_each_crtc'
- 'drm_for_each_crtc_reverse'
- 'drm_for_each_encoder'
- 'drm_for_each_encoder_mask'
- 'drm_for_each_fb'
- 'drm_for_each_legacy_plane'
- 'drm_for_each_plane'
- 'drm_for_each_plane_mask'
- 'drm_for_each_privobj'
- 'drm_mm_for_each_hole'
- 'drm_mm_for_each_node'
- 'drm_mm_for_each_node_in_range'
- 'drm_mm_for_each_node_safe'
- 'flow_action_for_each'
- 'for_each_acpi_dev_match'
- 'for_each_active_dev_scope'
- 'for_each_active_drhd_unit'
- 'for_each_active_iommu'
- 'for_each_aggr_pgid'
- 'for_each_available_child_of_node'
- 'for_each_bio'
- 'for_each_board_func_rsrc'
- 'for_each_bvec'
- 'for_each_card_auxs'
- 'for_each_card_auxs_safe'
- 'for_each_card_components'
- 'for_each_card_dapms'
- 'for_each_card_pre_auxs'
- 'for_each_card_prelinks'
- 'for_each_card_rtds'
- 'for_each_card_rtds_safe'
- 'for_each_card_widgets'
- 'for_each_card_widgets_safe'
- 'for_each_cgroup_storage_type'
- 'for_each_child_of_node'
- 'for_each_clear_bit'
- 'for_each_clear_bit_from'
- 'for_each_cmsghdr'
- 'for_each_compatible_node'
- 'for_each_component_dais'
- 'for_each_component_dais_safe'
- 'for_each_comp_order'
- 'for_each_console'
- 'for_each_cpu'
- 'for_each_cpu_and'
- 'for_each_cpu_not'
- 'for_each_cpu_wrap'
- 'for_each_dapm_widgets'
- 'for_each_dev_addr'
- 'for_each_dev_scope'
- 'for_each_dma_cap_mask'
- 'for_each_dpcm_be'
- 'for_each_dpcm_be_rollback'
- 'for_each_dpcm_be_safe'
- 'for_each_dpcm_fe'
- 'for_each_drhd_unit'
- 'for_each_dss_dev'
- 'for_each_dtpm_table'
- 'for_each_efi_memory_desc'
- 'for_each_efi_memory_desc_in_map'
- 'for_each_element'
- 'for_each_element_extid'
- 'for_each_element_id'
- 'for_each_endpoint_of_node'
- 'for_each_evictable_lru'
- 'for_each_fib6_node_rt_rcu'
- 'for_each_fib6_walker_rt'
- 'for_each_free_mem_pfn_range_in_zone'
- 'for_each_free_mem_pfn_range_in_zone_from'
- 'for_each_free_mem_range'
- 'for_each_free_mem_range_reverse'
- 'for_each_func_rsrc'
- 'for_each_hstate'
- 'for_each_if'
- 'for_each_iommu'
- 'for_each_ip_tunnel_rcu'
- 'for_each_irq_nr'
- 'for_each_link_codecs'
- 'for_each_link_cpus'
- 'for_each_link_platforms'
- 'for_each_lru'
- 'for_each_matching_node'
- 'for_each_matching_node_and_match'
- 'for_each_member'
- 'for_each_memcg_cache_index'
- 'for_each_mem_pfn_range'
- '__for_each_mem_range'
- 'for_each_mem_range'
- '__for_each_mem_range_rev'
- 'for_each_mem_range_rev'
- 'for_each_mem_region'
- 'for_each_migratetype_order'
- 'for_each_msi_entry'
- 'for_each_msi_entry_safe'
- 'for_each_net'
- 'for_each_net_continue_reverse'
- 'for_each_netdev'
- 'for_each_netdev_continue'
- 'for_each_netdev_continue_rcu'
- 'for_each_netdev_continue_reverse'
- 'for_each_netdev_feature'
- 'for_each_netdev_in_bond_rcu'
- 'for_each_netdev_rcu'
- 'for_each_netdev_reverse'
- 'for_each_netdev_safe'
- 'for_each_net_rcu'
- 'for_each_new_connector_in_state'
- 'for_each_new_crtc_in_state'
- 'for_each_new_mst_mgr_in_state'
- 'for_each_new_plane_in_state'
- 'for_each_new_private_obj_in_state'
- 'for_each_node'
- 'for_each_node_by_name'
- 'for_each_node_by_type'
- 'for_each_node_mask'
- 'for_each_node_state'
- 'for_each_node_with_cpus'
- 'for_each_node_with_property'
- 'for_each_nonreserved_multicast_dest_pgid'
- 'for_each_of_allnodes'
- 'for_each_of_allnodes_from'
- 'for_each_of_cpu_node'
- 'for_each_of_pci_range'
- 'for_each_old_connector_in_state'
- 'for_each_old_crtc_in_state'
- 'for_each_old_mst_mgr_in_state'
- 'for_each_oldnew_connector_in_state'
- 'for_each_oldnew_crtc_in_state'
- 'for_each_oldnew_mst_mgr_in_state'
- 'for_each_oldnew_plane_in_state'
- 'for_each_oldnew_plane_in_state_reverse'
- 'for_each_oldnew_private_obj_in_state'
- 'for_each_old_plane_in_state'
- 'for_each_old_private_obj_in_state'
- 'for_each_online_cpu'
- 'for_each_online_node'
- 'for_each_online_pgdat'
- 'for_each_pci_bridge'
- 'for_each_pci_dev'
- 'for_each_pci_msi_entry'
- 'for_each_pcm_streams'
- 'for_each_physmem_range'
- 'for_each_populated_zone'
- 'for_each_possible_cpu'
- 'for_each_present_cpu'
- 'for_each_prime_number'
- 'for_each_prime_number_from'
- 'for_each_process'
- 'for_each_process_thread'
- 'for_each_prop_codec_conf'
- 'for_each_prop_dai_codec'
- 'for_each_prop_dai_cpu'
- 'for_each_prop_dlc_codecs'
- 'for_each_prop_dlc_cpus'
- 'for_each_prop_dlc_platforms'
- 'for_each_property_of_node'
- 'for_each_registered_fb'
- 'for_each_requested_gpio'
- 'for_each_requested_gpio_in_range'
- 'for_each_reserved_mem_range'
- 'for_each_reserved_mem_region'
- 'for_each_rtd_codec_dais'
- 'for_each_rtd_components'
- 'for_each_rtd_cpu_dais'
- 'for_each_rtd_dais'
- 'for_each_set_bit'
- 'for_each_set_bit_from'
- 'for_each_set_clump8'
- 'for_each_sg'
- 'for_each_sg_dma_page'
- 'for_each_sg_page'
- 'for_each_sgtable_dma_page'
- 'for_each_sgtable_dma_sg'
- 'for_each_sgtable_page'
- 'for_each_sgtable_sg'
- 'for_each_sibling_event'
- 'for_each_subelement'
- 'for_each_subelement_extid'
- 'for_each_subelement_id'
- '__for_each_thread'
- 'for_each_thread'
- 'for_each_unicast_dest_pgid'
- 'for_each_vsi'
- 'for_each_wakeup_source'
- 'for_each_zone'
- 'for_each_zone_zonelist'
- 'for_each_zone_zonelist_nodemask'
- 'fwnode_for_each_available_child_node'
- 'fwnode_for_each_child_node'
- 'fwnode_graph_for_each_endpoint'
- 'gadget_for_each_ep'
- 'genradix_for_each'
- 'genradix_for_each_from'
- 'hash_for_each'
- 'hash_for_each_possible'
- 'hash_for_each_possible_rcu'
- 'hash_for_each_possible_rcu_notrace'
- 'hash_for_each_possible_safe'
- 'hash_for_each_rcu'
- 'hash_for_each_safe'
- 'hctx_for_each_ctx'
- 'hlist_bl_for_each_entry'
- 'hlist_bl_for_each_entry_rcu'
- 'hlist_bl_for_each_entry_safe'
- 'hlist_for_each'
- 'hlist_for_each_entry'
- 'hlist_for_each_entry_continue'
- 'hlist_for_each_entry_continue_rcu'
- 'hlist_for_each_entry_continue_rcu_bh'
- 'hlist_for_each_entry_from'
- 'hlist_for_each_entry_from_rcu'
- 'hlist_for_each_entry_rcu'
- 'hlist_for_each_entry_rcu_bh'
- 'hlist_for_each_entry_rcu_notrace'
- 'hlist_for_each_entry_safe'
- 'hlist_for_each_entry_srcu'
- '__hlist_for_each_rcu'
- 'hlist_for_each_safe'
- 'hlist_nulls_for_each_entry'
- 'hlist_nulls_for_each_entry_from'
- 'hlist_nulls_for_each_entry_rcu'
- 'hlist_nulls_for_each_entry_safe'
- 'i3c_bus_for_each_i2cdev'
- 'i3c_bus_for_each_i3cdev'
- 'ide_host_for_each_port'
- 'ide_port_for_each_dev'
- 'ide_port_for_each_present_dev'
- 'idr_for_each_entry'
- 'idr_for_each_entry_continue'
- 'idr_for_each_entry_continue_ul'
- 'idr_for_each_entry_ul'
- 'in_dev_for_each_ifa_rcu'
- 'in_dev_for_each_ifa_rtnl'
- 'inet_bind_bucket_for_each'
- 'inet_lhash2_for_each_icsk_rcu'
- 'key_for_each'
- 'key_for_each_safe'
- 'klp_for_each_func'
- 'klp_for_each_func_safe'
- 'klp_for_each_func_static'
- 'klp_for_each_object'
- 'klp_for_each_object_safe'
- 'klp_for_each_object_static'
- 'kunit_suite_for_each_test_case'
- 'kvm_for_each_memslot'
- 'kvm_for_each_vcpu'
- 'list_for_each'
- 'list_for_each_codec'
- 'list_for_each_codec_safe'
- 'list_for_each_continue'
- 'list_for_each_entry'
- 'list_for_each_entry_continue'
- 'list_for_each_entry_continue_rcu'
- 'list_for_each_entry_continue_reverse'
- 'list_for_each_entry_from'
- 'list_for_each_entry_from_rcu'
- 'list_for_each_entry_from_reverse'
- 'list_for_each_entry_lockless'
- 'list_for_each_entry_rcu'
- 'list_for_each_entry_reverse'
- 'list_for_each_entry_safe'
- 'list_for_each_entry_safe_continue'
- 'list_for_each_entry_safe_from'
- 'list_for_each_entry_safe_reverse'
- 'list_for_each_entry_srcu'
- 'list_for_each_prev'
- 'list_for_each_prev_safe'
- 'list_for_each_safe'
- 'llist_for_each'
- 'llist_for_each_entry'
- 'llist_for_each_entry_safe'
- 'llist_for_each_safe'
- 'mci_for_each_dimm'
- 'media_device_for_each_entity'
- 'media_device_for_each_intf'
- 'media_device_for_each_link'
- 'media_device_for_each_pad'
- 'nanddev_io_for_each_page'
- 'netdev_for_each_lower_dev'
- 'netdev_for_each_lower_private'
- 'netdev_for_each_lower_private_rcu'
- 'netdev_for_each_mc_addr'
- 'netdev_for_each_uc_addr'
- 'netdev_for_each_upper_dev_rcu'
- 'netdev_hw_addr_list_for_each'
- 'nft_rule_for_each_expr'
- 'nla_for_each_attr'
- 'nla_for_each_nested'
- 'nlmsg_for_each_attr'
- 'nlmsg_for_each_msg'
- 'nr_neigh_for_each'
- 'nr_neigh_for_each_safe'
- 'nr_node_for_each'
- 'nr_node_for_each_safe'
- 'of_for_each_phandle'
- 'of_property_for_each_string'
- 'of_property_for_each_u32'
- 'pci_bus_for_each_resource'
- 'pcl_for_each_chunk'
- 'pcl_for_each_segment'
- 'pcm_for_each_format'
- 'ping_portaddr_for_each_entry'
- 'plist_for_each'
- 'plist_for_each_continue'
- 'plist_for_each_entry'
- 'plist_for_each_entry_continue'
- 'plist_for_each_entry_safe'
- 'plist_for_each_safe'
- 'pnp_for_each_card'
- 'pnp_for_each_dev'
- 'protocol_for_each_card'
- 'protocol_for_each_dev'
- 'queue_for_each_hw_ctx'
- 'radix_tree_for_each_slot'
- 'radix_tree_for_each_tagged'
- 'rb_for_each'
- 'rbtree_postorder_for_each_entry_safe'
- 'rdma_for_each_block'
- 'rdma_for_each_port'
- 'rdma_umem_for_each_dma_block'
- 'resource_list_for_each_entry'
- 'resource_list_for_each_entry_safe'
- 'rhl_for_each_entry_rcu'
- 'rhl_for_each_rcu'
- 'rht_for_each'
- 'rht_for_each_entry'
- 'rht_for_each_entry_from'
- 'rht_for_each_entry_rcu'
- 'rht_for_each_entry_rcu_from'
- 'rht_for_each_entry_safe'
- 'rht_for_each_from'
- 'rht_for_each_rcu'
- 'rht_for_each_rcu_from'
- '__rq_for_each_bio'
- 'rq_for_each_bvec'
- 'rq_for_each_segment'
- 'scsi_for_each_prot_sg'
- 'scsi_for_each_sg'
- 'sctp_for_each_hentry'
- 'sctp_skb_for_each'
- 'shdma_for_each_chan'
- '__shost_for_each_device'
- 'shost_for_each_device'
- 'sk_for_each'
- 'sk_for_each_bound'
- 'sk_for_each_entry_offset_rcu'
- 'sk_for_each_from'
- 'sk_for_each_rcu'
- 'sk_for_each_safe'
- 'sk_nulls_for_each'
- 'sk_nulls_for_each_from'
- 'sk_nulls_for_each_rcu'
- 'snd_array_for_each'
- 'snd_pcm_group_for_each_entry'
- 'snd_soc_dapm_widget_for_each_path'
- 'snd_soc_dapm_widget_for_each_path_safe'
- 'snd_soc_dapm_widget_for_each_sink_path'
- 'snd_soc_dapm_widget_for_each_source_path'
- 'tb_property_for_each'
- 'tcf_exts_for_each_action'
- 'udp_portaddr_for_each_entry'
- 'udp_portaddr_for_each_entry_rcu'
- 'usb_hub_for_each_child'
- 'v4l2_device_for_each_subdev'
- 'v4l2_m2m_for_each_dst_buf'
- 'v4l2_m2m_for_each_dst_buf_safe'
- 'v4l2_m2m_for_each_src_buf'
- 'v4l2_m2m_for_each_src_buf_safe'
- 'virtio_device_for_each_vq'
- 'while_for_each_ftrace_op'
- 'xa_for_each'
- 'xa_for_each_marked'
- 'xa_for_each_range'
- 'xa_for_each_start'
- 'xas_for_each'
- 'xas_for_each_conflict'
- 'xas_for_each_marked'
- 'xbc_array_for_each_value'
- 'xbc_for_each_key_value'
- 'xbc_node_for_each_array_value'
- 'xbc_node_for_each_child'
- 'xbc_node_for_each_key_value'
- 'zorro_for_each_dev'

IfMacros: # 视为条件而非函数调用的宏,clang-format 13
- KJ_IF_MAYBE
IncludeBlocks: Preserve # include块拆分和排序,clang-format 7
IncludeCategories: # include分类
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$' # 在使用IncludeCategories将文件映射为主要的include文件时,允许在此给主要的include文件添加一个后缀,主要的include文件在排序时会放在顶部,clang-format 7
IncludeIsMainSourceRegex: '' # clang-format仅对main源文件(具有.c、.cc、.cpp、.c++、.cxx、.m、.mm扩展名)执行“main include file逻辑”,通过这个,可以将其它文件视为main源文件,clang-format 7
IndentAccessModifiers: false # 缩进public等访问修饰符,clang-format 13
IndentCaseBlocks: true # 缩进case块,clang-format 11
IndentCaseLabels: false # 缩进case标签
IndentExternBlock: AfterExternBlock # 缩进extern块,clang-format 11
IndentGotoLabels: false # 缩进goto标签,clang-format 10
IndentPPDirectives: None # 缩进预处理器指令,clang-format 6
IndentRequires: false # 在模板中缩进requires子句,clang-format 12,13,14
# IndentRequiresClause: false # 在模板中缩进requires子句,是IndentRequires在clang-format 15中的重命名
IndentWidth: 8
IndentWrappedFunctionNames: false # 缩进换行后的函数名
# InsertBraces: false # 在C++的控制语句后插入大括号,除非这些控制语句是在宏定义或者预处理指令里,clang-format 15
InsertTrailingCommas: None # 在数组或对象尾部插入‘,’,仅对JavaScript有效,插入‘,’与BinPackArguments冲突,不能同时启用,clang-format 11
JavaImportGroups: ['com', 'org'] # Java导入分组,clang-format 8
JavaScriptQuotes: Leave # JavaScript引号风格,保留原样
JavaScriptWrapImports: true # JavaScript import折行
KeepEmptyLinesAtTheStartOfBlocks: false # 保留块开头处的空行
LambdaBodyIndentation: Signature # lambda定义体缩进,clang-format 13
# Language: None # 在这里定义本节支持的语言
MacroBlockBegin: '' # 表示宏块开始的正则表达式
MacroBlockEnd: '' # 表示宏块结束的正则表达式
MaxEmptyLinesToKeep: 1 # 可保留的最大空行
NamespaceIndentation: None # 相对namespace的缩进
NamespaceMacros: # 视为namespace的宏,clang-format 9
- NAMESPACE

ObjCBinPackProtocolList: Auto # Objective-C相关,clang-format 7
ObjCBlockIndentWidth: 8
ObjCBreakBeforeNestedBlockParam: true # clang-format 11
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true

PPIndentWidth: -1 # 预处理器指令缩进宽度,设为-1(默认值)时,IndentWidth用于预处理器指令,clang-format 13
PackConstructorInitializers: CurrentLine # 构造器的初始化列表合并方式,clang-format 14

# Taken from git's rules
PenaltyBreakAssignment: 10 # clang-format 5
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 10
PenaltyBreakTemplateDeclaration: 10 # clang-format 7
PenaltyExcessCharacter: 100
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60

PointerAlignment: Right # 指针和引用的对齐风格:*和&是靠近变量名还是靠近类型名

RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
- ParseTestProto
- ParsePartialTestProto
CanonicalDelimiter: pb
BasedOnStyle: google

QualifierAlignment: Custom # 如何排列const/volatile之类的限定符,clang-format 14
QualifierOrder: ['restrict', 'static', 'const', 'constexpr', 'inline', 'volatile' , 'type'] # 限定符的排列顺序,clang-format 14
ReferenceAlignment: Right # 引用的对齐方式,如不定义,使用PointerAlignment的值,clang-format 13
ReflowComments: false # 是否重排注释
RemoveBracesLLVM: false # 根据LLVM编码风格移除C++控制语句中的非必需的大括号,clang-format 14
# RequiresClausePosition: WithPreceding # template中,requires子句的位置,clang-format 15
SeparateDefinitionBlocks: Always # 插入空行分离class、struct、enum、function等定义块,clang-format 14
ShortNamespaceLines: 1 # 多少行以内的namespace块被认为是短的,clang-format 13
SortIncludes: false # 是否排序include
SortJavaStaticImport: Before # 排序Java静态导入,clang-format 12
SortUsingDeclarations: false # 是否排序using,clang-format 5
SpaceAfterCStyleCast: false # C风格的类型转换后是否加空格
SpaceAfterLogicalNot: false # 逻辑非后是否加空格,clang-format 9
SpaceAfterTemplateKeyword: true # template关键词后是否加空格
SpaceAroundPointerQualifiers: Default # 环绕指针限定符的空格,clang-format 12
SpaceBeforeAssignmentOperators: true # 赋值运算符前是否加空格
SpaceBeforeCaseColon: false # 在case语句的:前插入空格,clang-format 12
SpaceBeforeCpp11BracedList: true # C++11的大括号内值列表前是否加空格,clang-format 7
SpaceBeforeCtorInitializerColon: true # 构造器初始化列表的:前面是否加空格,clang-format 7
SpaceBeforeInheritanceColon: true # 在定义继承的:前是否加空格,clang-format 7
SpaceBeforeParens: Custom # 开括号前何时应加空格
SpaceBeforeParensOptions: # 自定义{前的空格
AfterControlStatements: true
AfterForeachMacros: false
AfterFunctionDeclarationName: false
AfterFunctionDefinitionName: false
AfterIfMacros: false
AfterOverloadedOperator: false
# AfterRequiresInClause: true # clang-format 15
# AfterRequiresInExpression: false # clang-format 15
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true # 范围for语句里面的:前是否加空格,clang-format 7
SpaceBeforeSquareBrackets: false # []前是否加空格,不影响lambda表达式,影响数组定义,clang-format 10
SpaceInEmptyBlock: false # 空的块里面是否加空格,clang-format 10
SpaceInEmptyParentheses: false # 空的()里面是否允许空格
SpacesBeforeTrailingComments: 1 # 行尾注释符前的空格数
SpacesInAngles: Never # <>里面是否添加空格
SpacesInCStyleCastParentheses: false # C风格的强制转换括号里是否添加空格
SpacesInConditionalStatement: false # 条件语句里面条件两侧是否添加空格:如if ( a )
SpacesInContainerLiterals: false # 容器字面量(Objective C和JavaScript的数组及字典字面量)是否添加空格
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: 1
SpacesInParentheses: false # ()里面的左、右边界是否添加空格
SpacesInSquareBrackets: false # []里面的左、右边界是否添加空格
Standard: c++03 # 以此标准解析和格式化C++结构体
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
TypenameMacros: ['STACK_OF', 'LIST'] # 视为类型声明,而非函数调用的宏,clang-format 9
UseCRLF: false # 是否使用“\r\n”
UseTab: Always
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
...

继承配置

每个配置项都核对一遍,总是费时费力的,好在ClangFormat允许我们基于预定义的编码风格,仅修改自己需要的部分即可,这是设置BasedOnStyle配置项的值为预定义的编码风格名字来实现的。以下是一个类似于Linux kernel coding style的编码风格配置:

1
2
3
4
5
6
BasedOnStyle: LLVM
IndentWidth: 8
UseTab: Always
BreakBeforeBraces: Linux
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false

另一种继承方式,是在.clang-format文件中将BasedOnStyle的值设置为InheritParentConfig,此时,将向父目录逐级查找一个最靠近当前目录的.clang-format文件作为基础,再叠加本文件的配置。如果任一级父目录都找不到.clang-format文件,则使用–fallback-style选项指定的编码风格为基础,若未设置–fallback-style选项,默认为LLVM预定义编码风格。一种常见的情况是:为了最小化提交代码时的差异,往往是不开AlignConsecutiveAssignments(对齐连续赋值时的赋值符)、AlignConsecutiveDeclarations(对齐连续定义的变量名)、ReflowComments(重排注释)、SortIncludes(重排#include指令)这些选项的。但是在特定的子模块里面,却可能希望打开这些来获得一个更好的阅读效果,为此,就可以在子模块的.clang-format里面编写如下内容:

1
2
3
4
5
BasedOnStyle: InheritParentConfig
AlignConsecutiveAssignments: AcrossComments
AlignConsecutiveDeclarations: AcrossComments
ReflowComments: true
SortIncludes: CaseSensitive

对局部代码禁止格式化

工具并不是万能的,在有些时候,我们已经手工整理好一些内容,而不希望clang-format去改变它时,可以将它放在注释// clang-format off// clang-format on之间,或者/* clang-format off *//* clang-format on */之间。例如:

1
2
3
4
5
int formatted_code;
// clang-format off
void unformatted_code ;
// clang-format on
void formatted_code_again;

参考资料