<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/108726>108726</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Trailing commas in static initializer completely disables formatting for that initializer
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
detly
</td>
</tr>
</table>
<pre>
Take the following C code:
```c
typedef struct {
int one;
int extras[3];
} input_extras_foobar_t;
static input_extras_foobar_t input_extras_from_level(
unsigned int level, int really_long_arg)
{
input_extras_foobar_t val = {
.one = 1001, .extras = { [2] = !!((level - 1) & 1U) != !really_long_arg, [1] = !!((level - 1) & 2U) != !really_long_arg, [0] = !!((level - 1) & 4U) != !really_long_arg,},
};
return val;
}
```
And this `.clang-format`:
```yml
BasedOnStyle: WebKit
Language: Cpp
ColumnLimit: 88
```
Running `clang-format -i test.c` leaves the overly long initializer line completely untouched.
If I remove the outermost trailing comma, it _does_ get formatted as:
```c
typedef struct {
int one;
int extras[3];
} input_extras_foobar_t;
static input_extras_foobar_t input_extras_from_level(
unsigned int level, int really_long_arg)
{
input_extras_foobar_t val = { .one = 1001,
.extras = {
[2] = !!((level - 1) & 1U) != !really_long_arg,
[1] = !!((level - 1) & 2U) != !really_long_arg,
[0] = !!((level - 1) & 4U) != !really_long_arg,
} };
return val;
}
```
If I remove the trailing comma only for the `.extras` structure, I get a different result:
```c
typedef struct {
int one;
int extras[3];
} input_extras_foobar_t;
static input_extras_foobar_t input_extras_from_level(
unsigned int level, int really_long_arg)
{
input_extras_foobar_t val = {
.one = 1001,
.extras = { [2] = !!((level - 1) & 1U) != !really_long_arg,
[1] = !!((level - 1) & 2U) != !really_long_arg,
[0] = !!((level - 1) & 4U) != !really_long_arg },
};
return val;
}
```
I understand that trailing commas are sort-of used to change line breaking/block indent behaviour for initializer lists. However, I'd expect that having both trailing commas here would combine the behaviour, like so:
```c
typedef struct {
int one;
int extras[3];
} input_extras_foobar_t;
static input_extras_foobar_t input_extras_from_level(
unsigned int level, int really_long_arg)
{
input_extras_foobar_t val = {
.one = 1001,
.extras = {
[2] = !!((level - 1) & 1U) != !really_long_arg,
[1] = !!((level - 1) & 2U) != !really_long_arg,
[0] = !!((level - 1) & 4U) != !really_long_arg,
},
};
return val;
}
```
Completely refusing to format the expression itself is quite surprising.
This appears in `clang-format` 18 and 20.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsV1Fv4zYM_jXKC5HAlmMnefDDNUGwYgcM2G7YYyDbtKNVljyJSi_79YPktE3S7tYN7YBhLQK3IkXqs_p9JCOck51GLFl-w_LNRHjaG1s2SOo4qUxzLL-IOwTaI7RGKXMvdQdrqE2DLPvEkg1LHp5FMn7qcU3HARtswZH1NQFb3Ix2AACpCYxGll3Z8CtZ4Vh-k7F88-hliw1IPXjajf5da0wl7I6edsSnI0GyfnnrldWafqfwgIrx5RMEr-NlNBHLyb2OC4tCqeNOGd3thO0YXz1Au3iDlw4-CAUs21xeQPiZGY3RkyZJGg6ajaEPu4HlN5zlm3HN0_hZMr6MyGAKKeMrYLyA9Ofxr_S08xnadciVvioXf1Wu5FW55n-Ziy024fl4L2F9-U8NVovkrQ43ec6JK9qdB33SDdBeOmBFMquV0N20NbYXFPb9CW2PvRotN8Jh84P-iY4qcBx-wep7SaPvs9CdF120r4dhNK6N8r3-LHtJwb5cfgPZj17rIKGgkzNcMJVA6GhWsyIBheKALorOHNCqI4QrA6klSaHk72hBSY1Qm35QSKiO4DUZX--xmZ2fdtvCLVjszWGUsPGEtjeOgKyQKgCpTd-LSHOCXWPQ7aBDghEWYQPCfQj97wr9mbZPsVcKv6wHkf9vJ_kXk79VDXgx-ZsVhYvkgRRvVBau5XApAjBaHQPxoy9UjhNLi-TEbW8x8OQ2KkRAI9sWLUbWOK_on-rkfyqSb3fDK-_7tcb_qE7gnVrnLXjdoHUkYg8V163CgbAIzliamha8wwbIQL0XusOxK1UWxZ3UHePbSpn6DqRugkgq3IuDNN5GjV02M0duBt-ZezygjRJjfNEAfh2wphFFiNUdVIb2zxDt0SLcG6-aYKkCiCDhxwNDRiXvAuyPXvYvyvSjv72uv72HjtdPs6HF1rsgFzKnuS7KA78OFp2TRoMkh6oF6eA3LwnBeTtYGWIuxskvYaQWw4DCOpD6eogNjTJdQigcPJlNmjJrVtlKTLBMF7zIiny5yCb7MmvnVbGoeZXmgURZu8rqpsUiLZqq4ryeyJInfJ6s0jzhyTzjs4LneTLHJG-EECuBbJ5gL6SaKXXoZ8Z2E-mcxzJNlgteTJSoULn4jZZzjfcQvYwH5k1sGYKmle8cmydj5XlMQ5IUll-uyovU8KjSp6J1Nnw30olKoXuYmkPsOEcIOo-ZeKvKPdEQR2q-ZXzbSdr7alabnvFtwHH6NR2s-RVrYnwb0TvGt6fXO5T8jwAAAP__-6uDlQ">