summaryrefslogtreecommitdiffstats
path: root/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/documentation/preprocessor_indentation.txt
blob: 6db89502c29482ef671942c91238c57b00c6d9f6 (plain)
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

Preprocessor blocks can arbitrarily alter the program flow and make indenting
code a challenging task.

This file covers the following topics:
1) Uncrustify approach to indentation of preprocessor blocks
2) Rationale for the chosen approach
3) Recommendations for the user


---------------------------------------------------------
Uncrustify approach to indentation of preprocessor blocks
---------------------------------------------------------

Uncrustify handles different preprocessor blocks in different ways.
There are just three simple rules to remember.

A. #ifdef/#endif block
----------------------
The contents of the block are indented starting at the same brace level of the
code preceding the block. Once #endif is reached, any indentation change caused
by the block is discarded and the following code continues at the same brace
level of the code preceding the block.

B. #ifdef/#elif/#else/#endif block
----------------------------------
The contents of the #ifdef part of the block are indented starting at the same
brace level of the code preceding the block.
Once an #elif/#else is reached, the indentation restarts at the brace level of
the code preceding the #ifdef part of the block. This is repeated for each
#else and #elif part.
Once #endif is reached, the following code continues at the same brace level
reached at the end of the #ifdef part.

C. #define block
----------------
The contents of the block are indented starting anew, therefore not following the
indentation of the code preceding the block. Once the #define ends, any indentation
change caused by the block is discarded and the following code continues at the same
brace level of the code preceding the block.


---------------------------------
Rationale for the chosen approach
---------------------------------

Preprocessor blocks can be very hard to handle and there is no definitive
correct way that works in all situations. Therefore a compromise approach is
required, coupled with warning to the user when tricky code is encountered.

A. #ifdef/#endif block
----------------------
Let's start with the simplest case, a balanced #ifdef/#endif block. This is a
block that starts and ends at the same brace level. For example:

    some code A
  #ifdef TEST
    some code B
  #endif
    some code C

or

    some code A
  #ifdef TEST
    {
      some code B
    }
  #endif
    some code C

These cases are very easy to handle, since the indentation before, through and after
the preprocessor block is consistent. There is no alteration of the brace level
from 'some code A' to 'some code C'. Rule A applies nicely to the above code.

Let's now look at a more complex example.

    some code A
  #ifdef TEST
    {
      some code B
  #endif
    some code C
  #ifdef TEST
      some code D
    }
  #endif
    some code E

This contains two unbalanced #ifdef blocks. Most likely the programmer intended to
use them in pair, but that is not important when it comes to indentation. The code
above could be indented as:

    some code A
  #ifdef TEST
    {
      some code B
  #endif
    some code C
  #ifdef TEST
      some code D
    }
  #endif
    some code E

or as:

    some code A
  #ifdef TEST
    {
      some code B
  #endif
      some code C
  #ifdef TEST
      some code D
    }
  #endif
    some code E

Note how 'some code C' is indented differently in the two cases: in the first, the
indentation change caused by the first #ifdef block is discarded, while in the
second it is taken into consideration.
Depending on the options used at compile time, the code in the preprocessor blocks
could be included or not included in the final code, therefore none of the two
options is superior to the other. A better approach would be to avoid the use
of unbalanced preprocessor blocks, so that indentation of the code could be uniquely
defined.
Uncrustify follows the first version, discarding indentation changes caused by
the #ifdef block. Warning messages about unbalanced preprocessor blocks can optionally
be printed by using the option 'pp_warn_unbalanced_if'.

B. #ifdef/#elif/#else/#endif block
----------------------------------
Let's start with the simplest case, a balanced #ifdef/#else/#endif block. This is a
block where each part starts and ends at the same brace level. For example:

    some code A
  #ifdef TEST
    some code B
  #else
    some code C
  #endif
    some code D

or

    some code A
  #ifdef TEST
    {
      some code B
    }
  #else
    {
      some code C
    }
  #endif
    some code D

or even:

    some code A
  #ifdef TEST
    {
      some code B
    }
  #else
    some code C
  #endif
    some code D

These cases are very easy to handle, since the indentation before, through and after
the preprocessor blocks is consistent. There is no alteration of the brace level
from 'some code A' to 'some code D'. Rule B applies nicely to the above code.

Let's now look at a more complex example.

    some code A
  #ifdef TEST
    {
      some code B
  #else
    some code C
  #endif
    some code D
  #ifdef TEST
      some code E
    }
  #else
    some code F
  #endif
    some code G

This once again raises the question of where 'some code D' should be placed and
there is no unique best choice.
Uncrustify has chosen (for reasons explained further below) to:
- indent each part of an #ifdef/#elif/#else/#endif block starting at the brace
level of the code preceding #ifdef.
- continue after #endif at the indentation level reached at the end of the #ifdef
part.
This would result in the following formatted code:

    some code A
  #ifdef TEST
    {
      some code B
  #else
    some code C
  #endif
      some code D
  #ifdef TEST
      some code E
    }
  #else
      some code F
  #endif
    some code G

And yes, the indentation of 'some code F' may surprise you a bit.
Here is an even trickier example:

    some code A
  #ifdef TEST
    some code B
  #else
    {
      some code C
  #endif
    some code D
  #ifndef TEST
      some code E
    }
  #else
    some code F
  #endif
    some code G

which results in this bizarre output, where 'some code G' is no
longer aligned with 'some code A':

    some code A
  #ifdef TEST
    some code B
  #else
    {
      some code C
  #endif
    some code D
  #ifndef TEST
    some code E
  }
  #else
    some code F
  #endif
  some code G

So why not simply discard all the indentation changes created by an
#ifdef/#elif/#else/#endif block? The answer is simple: to make sure things
still work fine after the #endif line! Without going into too much detail here
(see the overview.odt and theory.txt files for more info) in addition to the
visible braces, there is a thing called 'virtual braces' which also affects
indentation. A common use of #ifdef/#elif/#else/#endif blocks is to do some
different things on the same set of variables. In this case, there may not be
any visible brace, but virtual braces may get modified between the code before
and after the preprocessor block. Throwing away the whole thing would result
in the code after #endif being formatted in a completely wrong manner.
As an example, consider this piece of code:

  some code A
  if (cond1)
    some var = value1;
  else
    some var =
  #ifdef TEST
      value2;
  #else
      value3;
  #endif
  some code B

The formatted version looks exactly like the original. But if the complete
#ifdef/#else/#endif block was thrown away, the result would be as if 'some code B'
was being indented as part of the else (not #else) block, at a position just after
the = symbol. By retaining the changes made in the #ifdef part, the 'else' block
is correctly handled and 'some code B' is indented as per its original position.

C. #define block
----------------
Here is an example showing how #define works. The following code:

    {
    {
    some code A
    #define TEST \
    { \
    some defs \
    }
    some code B
    }
    }

would be formatted as:

    {
      {
        some code A
    #define TEST \
    { \
      some defs \
    }
        some code B
      }
    }

Notice how 'some code B' and 'some code A' are indented in the same way, while the
#define body starts from anew.


----------------------------
Recommendations for the user
----------------------------
The golden rule is to avoid unbalanced preprocessor blocks. This keeps things
simple and indentation can be uniquely defined. Existing unbalanced blocks should
be reworked so that all braces are properly balanced, either outside or inside the
preprocessor blocks.
If you have a huge code base, it may be difficult to quickly find offending blocks.
If the option 'pp_warn_unbalanced_if' is set to true, Uncrustify will print warning
messages at the end of each unbalanced preprocessor block part based on the following rules:

1) unbalanced #ifdef part
This works for either an #ifdef/#endif block or the first part of an #ifdef/#elif/#else/#endif
block. If the #ifdef ends at a brace level different from where it starts, a message will
be displayed, highlighting both the starting and ending indentation levels.

2) unbalanced #elif or #else part
If such part ends at a different brace level than the corresponding #ifdef part, a message
will be displayed highlighting the ending indentation levels of both the part in question
and the respective #ifdef part.

3) unbalanced #define
If a #define ends at a brace level different from where it starts, a message will
be displayed, highlighting the ending indentation level.

Here is an example with a mix of balanced and unbalanced blocks, with line numbers in front
for easier reference:

  1    void Fun(int &data)
  2    {
  3      data = 1;
  4
  5    #ifdef MANUAL_LAYOUT
  6    {
  7      data = 2;
  8    }
  9    #endif
 10
 11    #ifdef MANUAL_LAYOUT
 12    {
 13      {
 14      data = 2;
 15    #elif TEST1
 16      data = 21;
 17    #elif TEST2
 18    {
 19      data = 22;
 20    #elif TEST3
 21      {
 22        {
 23      data = 22;
 24    #else
 25      {
 26        {
 27      data = 22;
 28    #endif
 29
 30      data = 3;
 31
 32    #ifdef MANUAL_LAYOUT
 33    {
 34      data = 4;
 35    #else
 36      data = 5;
 37    #endif
 38
 39    #ifdef MANUAL_LAYOUT
 40      data = 6;
 41    #else
 42      data = 7;
 43    #endif
 44
 45    #ifdef MANUAL_LAYOUT
 46      }
 47    }
 48    #endif
 49
 50    #ifdef MANUAL_LAYOUT
 51    }
 52    #endif
 53
 54      data = 8;
 55
 56      data = 9;
 57    }

These are the warning messages related to unbalanced preprocessor blocks
printed by Uncrustify when 'pp_warn_unbalanced_if' is true.

check(236): orig line is 15, unbalanced #if block braces (1), in-level is 1, out-level is 3
check(248): orig line is 17, unbalanced #if-#else block braces (1), #else out-level is 1, #if out-level is 3
check(248): orig line is 20, unbalanced #if-#else block braces (1), #else out-level is 2, #if out-level is 3
check(236): orig line is 35, unbalanced #if block braces (1), in-level is 3, out-level is 4
check(291): orig line is 37, unbalanced #if-#else block braces (2), #else out-level is 3, #if out-level is 4
check(321): orig line is 48, unbalanced #if block braces (2), in-level is 4, out-level is 2
check(321): orig line is 52, unbalanced #if block braces (2), in-level is 4, out-level is 3